Receiving byte with value of 0x1A

Zenerdiode

Active Member
Licensed User
I'm writing an app to receive data via the serial port and display the byte values. I've stripped out the project for the attachment. In the 'On Com' event, you'll see that at first I was using Port.InputString - however if the byte was greater than 0x7F it was changed to 0x3F ('?'), presumably by Serial2.dll.

I changed to using Port.InputArray and now receive the full range of bytes from 0x00 to 0xFF, but now, if opto compiled, I get the error attached if 0x1A is sent. If legacy or IDE compiled, sending a single 0x1A byte fires 'On Com' twice and opto gives the error. I've included an app that may be compiled for a device and connected with an RS232 cable but I appreciate not many will have that facility.

What does Port.TimeOut actually do?

Finally, if I use CTSHandshaking=True, do I still have to assert RTSEnable?
 

Attachments

  • Receive.zip
    11.7 KB · Views: 241

agraham

Expert
Licensed User
Longtime User
however if the byte was greater than 0x7F it was changed to 0x3F ('?'), presumably by Serial2.dll.
Yes, that is expected behaviour. InputString is based on a .NET Stream. Streams support encodings, Unicode, ASCII or code pages. The default is ASCII whose valid characters are 0x00 to 0x7F. This can't be changed in Basic4ppc except by using the Door library.

I changed to using Port.InputArray and now receive the full range of bytes from 0x00 to 0xFF, but now, if opto compiled, I get the error attached if 0x1A is sent. If legacy or IDE compiled, sending a single 0x1A byte fires 'On Com' twice and opto gives the error.
I can't explain what is happening except to remark that it is probably not coincidental that 0x1A is the Ctl-Z character which is used for XonXoff handshaking if it were enabled.

What does Port.TimeOut actually do?
When bytes are read or written to the port if the read or write doesn't succeed within the timeout then the call returns. In Serial2 the read process is detached from this by having a buffer in which incoming bytes are assembled and the read is done on this buffer so a timeout on read can't occur. The Output methods do write directly and so might timeout if the handshake method in use is preventing data being sent. The default timeout is set to 100mS when you open the port.

Finally, if I use CTSHandshaking=True, do I still have to assert RTSEnable?
No, it is an error to do so and you should get an exception thrown if you try when either CTSHandshaking or (strangely!) XonXoffHandshaking are true. When you enable CTSHandshaking the system manages the state of the RTS pin.
 

Zenerdiode

Active Member
Licensed User
Many thanks Andrew :)

0x1A is the control character 'SUB' or substitute (with 0x11 and 0x13 being XON and XOFF respectively)

A work around I've discovered is to trap the error and do nothing with it - as the sub still returns the value 1A to the calling sub. Its not my preferred solution.

B4X:
Sub Port_OnCom
   ErrorLabel(BadHex)
   Buffer()=Port.InputArray
   For i = 0 To ArrayLen(Buffer())-1
      ReceivedString=ReceivedString&Chr(Buffer(i))
   Next
   Return
   BadHex:
   Return
End Sub

This only works for Optimised compilation, the OnCom still gets fired twice on legacy or IDE. That doesn't really concern me as the app will be compiled with optimisation.
 

agraham

Expert
Licensed User
Longtime User
0x1A is the control character 'SUB' or substitute (with 0x11 and 0x13 being XON and XOFF respectively)
:signOops: engage brain before writing down quick assumptions! Ctl-Z rang a bell as special character for something so I blithely wrote down a rubbish assumption :sign0013: It is of course the old DOS end-of-file character for text files. I'm sure I have had RS232 comms issues with it in the past - problem is I can't remember what they were :(
 

agraham

Expert
Licensed User
Longtime User
I connected one of my laptops to my desktop by RS232 and got the same results as you. Here's what I think is happening based on this Serial Communication with Visual Basic .NET

The .NET SerialPort class apparently harks back to the DOS days and treats 0x1A as a special case and creates an additional OnCom event when one arrives to notify the fact. This extra event can be identified in VB.NET or C# code by an event argument but you don't get this with the Serial2 library. This event is additional to the one for the character and probably explains why you get two events in legacy/IDE.

I suspect that the error in an optimised app is caused by SerialPort.InputArray returning a null reference for this extra event. Why this doesn't error in the IDE I have no idea but the hypothesis fits the facts. A workaround would appear to use SerialPort.InputString but we need to get the full range of characters which it does not by default. This can be accomplished by assigning an Encoding object to the SerialPort using the Door library as in the attached library :sign0162:
 

Attachments

  • ReceivesOKnow.sbp
    2.3 KB · Views: 220

Zenerdiode

Active Member
Licensed User
Almost, although byte values between 0x80 and 0x9F are returning peculiar values. For example, send 0x80 and it is interpreted as 0x20AC or 8364. I can't work out the relationship to 128. Is it a codepage thing?

Ctl-Z rang a bell ...

So does Ctl-G ;)
(I'll erm, I'll get my coat...)
 

agraham

Expert
Licensed User
Longtime User
Let's forget the String idea, Unicode gets in the way whatever code page you use :(

I have single stepped the Serial library code in VS2005 and what is happening is almost exactly as I said. Two events are raised for 0x1A, when you do InputArray for the first event you get the character and empty the input buffer, the second event also does InputArray but as the buffer is empty a null reference is returned. The IDE, being interpreted, seems to trap this null and leaves Buffer() with its previous contents, hence the apparent duplication of the character(s) previously read, whereas an optimised compiled app just tries the assignment and causes an exception.

Attached is a version of the Serial library that does not raise the extra EOF event. I'll raise the issue as a bug and hopefully Erel will make an official update of Serial2.
 

Attachments

  • SerialEx.zip
    4 KB · Views: 238

Zenerdiode

Active Member
Licensed User
:sign0188:

Sincere thanks for your work on this. I've updated my project to include your SerialEx. I hope Erel has a chance to update Serial2 - perhaps even allowing us to switch on the enumeration - just in case someone somewhere needs the use of 0x1A EOF.

The article you directed me to made for interesting reading. I would have good use for the events listed in the SerialPort Events paragraph. I'll tag a request to your bug report requesting the feasibility.

Christopher
 
Top