Binary hex string conversions


#1

I’ve integrated a couple of devices recently that communicate via TCP/IP and have commands and responses that are built in binary hex strings. I did not see a built-in function that deals with this, but maybe I missed something.

It seems that the built-in NumberToHexString and HexStringToNumber commands (as well as the legacy NumberToFormattedHexString) are based on ascii strings, so that an ascii string “FF” converts to 255. However, in binary hex, “46 46” is what goes out the comm handle if that string is sent.

What I would like is to be able to convert 255 to the binary hex string “FF”, and vice versa. I think probably the (Transmit)ReceiveNumericTable(Ex) commands do this, but they require each element to be of the same size, and some message strings that I want to build or parse aren’t that nicely structured. They also communicate directly with the comm handle, which means the messages can’t be easily stored and handled in separate operations.

So, attached are a couple simple subroutines that do this for me, and a chart that demonstrates their usage. All of the subroutines are “additive” to whatever output variable is assigned. In other words, for the IntegerToHex routine, the new hex string will be appended onto the assigned string variable. For the HextoI32(64) routines, the new integer will be added to the assigned integer variable.

It is configured to use the PacSim control engine, but you might need to adjust it for your system. The “IntegerToHex” routine will handle I32 or I64 inputs, and will only give you the least significant bits if the receiving string isn’t big enough.

I couldn’t think of a way to make the hex to int conversion data type insensitive, so there are separate routines for HexToI32 and HexToI64.

The routines handle negative numbers correctly, and let you specify whether the byte sequence is big-endian or little-endian.

At some point, I may look at doing the same thing for floats, but I haven’t needed it so far.

In dealing with I64’s, I ran into a number of situations where constants need to be cast into 64 bits to keep the calculation at 64 bits. For example, the constant “8” would need to be “8i64”.

The attachment has been updated thanks to some suggestions Mary made below. The code is much cleaner than the original version.


#2

Wow, thanks for sharing your code!

One of the things I love about OptoStuff is how there are many ways to solve a particular problem, and not necessarily a “right” answer. I always encourage people to write a little more code if that is easier to understand than some fancy shorthand that may give you a headache.

For example, on your first IntegerToHex logic, I’d do it a little differently, then again, I’m kind of a nerd. Here’s what seemed intuitive to me when I needed to do similar conversions in the past (this is leveraging some OptoScript shorthand you might not have used before).

Basically it boils down to 4 bytes you want to pull out of the 4-byte int32 and stack up as a “string,” which you could do this way (also showing the reverse here in OptoScript):




I’m just using the OptoScript << and >> (bit shift) vs. your Power function, and the shorthand of the [char number] vs. GetNthCharacter but same idea. Hope it makes sense.

There’s one other method that pops in my head which I’ll share here in a bit if I can get it working…


#3

Okay, this one, like the last example I gave, doesn’t have an option for Endian-ness and also won’t work on PAC SIM. However, if you have SoftPAC (which comes with PAC Project Pro, or as an add-on to Basic), or a hardware-based PAC, you can leverage the mem map and easily convert a whole TABLE of integers into a binary string, if you’d like. Not bit shifting or Powers of bitands either!

The idea here is that our mem map, in particular the scratch pad area, is just a hunk of memory that you can read and write to. It’s not “strongly typed” in that, we don’t care what data you’re writing to, say, the scratch pad int section.

So… if you write your int table to the mem map (see 1st command below), then read it from the mem map into a string, you’re done. Your whole table of ints loaded into that string.

Step 1: Write your table to the mem map



Step 2: read it in as a string, and…

TA DA! Multiple ints (in this case, 10) converted into your string:

However, since you mentioned TCP/IP, I’m assuming these values are embedded into a longer message? (Because we do have commands like TransmitNumericTable which you could also use, even if it’s only one number you’re transmitting…)

I hope that all makes sense. Getting a little “outside the box” on that mem map method!

In any case, I’m glad you asked, I’ve been working on some training/video content related to types and converting between them, so your timing is perfect.

Cheers,
-OptoMary


#4

Yeah, the mem map solution is a little bit out there, especially when I’ve come to appreciate how nice it is to run PacSim and Wireshark to get the communication clean before moving it over to the actual hardware (which Wireshark can’t so easily intercept).

I’ll bet the bitwise operator approach will be much easier on the processor than my original approach. I’ve updated the attachment based on this technique.

Thanks so much for your feedback!


#5

I have been working with the new version of PAC Control, and noticed the new set of “Pack” commands that appear to do what I was trying to accomplish with these subroutines. I haven’t tested them yet since I haven’t moved to a firmware version that supports the commands. Hopefully those commands are somewhat faster than my subroutines… despite the educational value in making them, my chart loop times took a major hit when I tried to use them. To keep the charts faster, I am using the direct commands as Mary suggested in post 2, which come a lot more naturally now that I understand how to think about it.