When retrieving data from instrumentation, especially serial devices, the data often arrives as an array of bytes. These bytes however, represent numbers in different forms. For example, the two bytes, 10 and 15 could represent two 8 bit numbers, or they could represent a single 16 bit number. Converting these two numbers is relatively straight forward using bitwise operators, but gets much more complicated when the bytes represent floating point values. To help with either of these cases, DAQFactory offers a collection of functions for converting an array of bytes into a single value. All these functions start with "To.". Each function takes an array of values. The size of the resultant type determines the number of columns required in the array. You can have one or more rows to convert multiple values. The functions return an array of values with one column. For example, if you did To.Word({{10,20},{30,40}}) you'd get {5130,10270}.
Byte(): converts the given number into a signed byte (8 bit) sized value.
To.Byte(253) returns -3
uByte(): converts the given number into an unsigned byte sized value. This is only marginally faster than just doing % 256, but possibly a bit clearer.
To.uByte(259) returns 3
Word(): converts the given number into a signed word (16 bit) value.
To.Word({{0,128}}) returns -32768
uWord(): converts the given number into an unsigned word value.
To.uWord({{0,128}}) returns 32768
rWord(): converts the given number into a signed word value by reversing the bytes to Big Endian (most significant byte first)
To.rWord({{0,128}}) returns 128
urWord(): converts the given number into a unsigned word value by reversing the bytes to Big Endian (most significant byte first)
To.urWord({{0,128}}) returns 128
Long(): converts the given number into a signed double word (32 bit) value.
To.Long({{0,128,0,128}}) returns -2147450880
uLong(): converts the given number into an unsigned double word value.
To.uLong({{0,128,0,128}}) returns 2147516416
rbLong(): converts the given number into a signed double word value by reversing the bytes in each word to Big Endian (most significant byte first). The words are left as Little Endian (least significant word first).
To.rbLong({{0,128,0,128}}) returns 8388736
urbLong(): converts the given number into a unsigned double word value by reversing the bytes in each word to Big Endian (most significant byte first). The words are left as Little Endian (least significant word first).
To.urbLong({{0,128,0,128}}) returns 8388736
rwLong(): converts the given number into a signed double word value by reversing the words to Big Endian (most significant word first). Bytes in each word are left as Little Endian (least significant byte first).
To.rwLong({{0,128,0,128}}) returns -2147450880
urwLong(): converts the given number into a unsigned double word value by reversing the words to Big Endian (most significant word first). Bytes in each word are left as Little Endian (least significant byte first).
To.urwLong({{0,128,0,128}}) returns 2147516416
Float(): converts the given number into a 32 bit floating point value (IEEE format).
To.Float({{3,4,66,69}}) returns 3104.251
rwFloat(): converts the given number into a 32 bit floating point value, reversing the words
To.rwFloat({{3,69,66,69}}) returns 2100.329
rbFloat(): converts the given number into a 32 bit floating point value, reversing the bytes
Double(): converts the given number into a 64 bit floating point value (IEEE format).
To.Double({{3,69,66,69,3,4,28,65}}) returns 459008.818
In addition to the above To functions there is one additional function for converting an integer into its bit array:
Bit(): converts the given number to an array of bits. If you provide a single number to this function, it will return a 32 element array of the bits that make up that number. If you provide an array of numbers, a 2 dimensional array is returned. In both cases, the 32 elements are in the second dimension, with the least significant bit first. So:
To.Bit(3) returns {{1,1,0,0,0,0,0,0,....,0}}
To.Bit({3,4}) returns {{1,1,0,0,0,0...},{0,0,1,0,0,0,0,....}}
The above results are truncated for clarity, but in fact there will be 32 columns in each result. The default is to convert to 32 bits. If you want less bits, specify it as the second parameter of the function:
To.Bit({3,4},8) returns {{1,1,0,0,0,0,0,0},{0,0,1,0,0,0,0,0}}
Either way, you can then access individual bits using standard subsetting:
Private bitarray = To.Bit(MyChannel[0])
if (bitarray[0][4])
.. do something
endif
bitarray[0][6] = 1 // set a bit
Out = From.Bit(bitarray)
Notice that we have to subset in the second dimension, not the first, to get a particular bit. If you are only converting a single value and want to avoid this you could always use the Transpose function:
Private bitarray = Transpose(To.Bit(MyChannel[0]),0)
if (bitarray[4])
.. do something
endif
At the end of the first example, we set a single bit and then used the From.Bit() function described below to convert the bit array back into its numeric representation. Note that if you do this in the second example after transposing, you will need to transpose back before calling From.Bit().
HexString(array): converts an array of numbers (each from 0 - 255) into a hex string. The hex string is formatted for use in setting blob data in SQL statements.
To.HexString({1,2,3}) returns the string "010203"
To.HexString supports multicolumn data allowing you to convert numbers larger than byte size into a hex string. You have to convert the numbers into byte arrays (using the appropriate from. function), but even though the result of this will be a two dimensional array of bytes, To.HexString will convert this into a single hexstring. For example:
To.HexString(from.urWord({65535,32767,3})) returns the string "FFFF7FFF0003"
Performing the direct opposite function as the To functions, the From functions allow you to convert a single value into its byte pattern based on a particular format. For example, the number 515 could be represented in a two byte word as 3 and 2 or a floating point value as the 4 bytes, 0, 0, 23 and 67. Each From functions take a value and return an array of bytes. All the functions start with "From.". Like the To functions, you can pass an array of values to convert multiple values at once. The resultant array will have the same number of rows as the original array, but as many columns as the size you are converting from. So, From.Word({5130,10270}) will give you {{10,20},{30,40}}. Note that these functions are designed for you to pass in values that are within the range of the given type you will get . For example, the range of a signed byte value is -127 to 127.
Byte(): converts the given signed byte value into an unsigned byte format.
From.Byte(-3) returns 253
uByte(): converts the given unsigned byte value into an unsigned byte format. This actually does the exact same thing as Byte() and is a pretty useless function, but we've provided it when you want clarity in your code.
From.uByte(3) returns 3
Word(): converts the given signed word value into an array of unsigned bytes putting the least significant byte first.
From.Word(-32768) returns {{0,128}}
uWord(): converts the given unsigned signed word value into an array of unsigned bytes putting the least significant byte first.
From.uWord(32768) returns {{0,128}}
rWord(): converts the given signed word value into an array of unsigned bytes putting the most significant byte first.
From.rWord(128) returns {{0,128}}
urWord(): converts the given unsigned word value into an array of unsigned bytes putting the most significant byte first.
From.urWord(128) returns {{0,128}}
Long(): converts the given signed double word value into an array of unsigned bytes with the least significant byte first.
From.Long(-2147450880) returns {{0,128,0,128}}
uLong(): converts the given unsigned double word value into an array of unsigned bytes with the least significant byte first.
From.uLong(2147516413) returns {{0,128,0,128}}
rbLong(): converts the given signed double word value into an array of unsigned bytes with the bytes in each word reversed from standard Little Endian format of From.Long().
From.rbLong(-2147450880) returns {{128,0,128,0}}
urbLong(): converts the given unsigned double word value into an array of unsigned bytes with the bytes in each word reversed from standard Little Endian format of From.uLong().
From.urbLong(2147516413) returns {{128,0,128,0}}
rwLong(): converts the given signed double word value into an array of unsigned bytes with the words reversed from standard Little Endian format of From.Long().
From.rwLong(-2147450880) returns {{0,128,0,128}}
urwLong(): converts the given signed double word value into an array of unsigned bytes with the words reversed from standard Little Endian format of From.uLong().
From.urwLong(2147517413) returns {{0,128,0,128}}
Float(): converts the given IEEE floating point value into an array of unsigned bytes.
From.Float(3104.251) returns {{4,4,66,69}}
rwFloat(): converts the given floating point value into an array of unsigned bytes with the words reversed from IEEE format.
From.rwFloat(3104.251) returns {{66,69,4,4}}
rbFloat(): converts the given floating point value into an array of unsigned bytes with the bytes reversed from IEEE format.
Double(): converts the given IEEE double precision (64 bit) floating point value into an array of unsigned bytes.
From.Double(459008.818) returns {{193,202,161,69,3,4,28,65}}
In addition to the above From functions there is one additional function for converting an array of bits to integers:
Bit(): converts the given array of bits to its numeric representation. Unlike To.Bit(), you do not have to provide all 32 bits. DAQFactory will assume any bits not provided are 0. The least significant bit is always first in the array. Here are some examples:
From.Bit({{1,1,0,1}}) returns 11. Note how the array of bits is in the second dimension.
From.Bit({1,1,0,1},{0,1,1,0}}) returns {11,6}
In a more programmatic way:
Private bitarray
bitarray[0][3] = HeaterOn
bitarray[0][1] = ValveState
bitarray[0][0] = SwitchState
Out = From.Bit(bitarray)
Notice that we have to subset in the second dimension, not the first, to set a particular bit. This is not required if you are only converting one value at a time, but you can convert a full matrix of bits to multiple values this way.
Both these examples also show a trick when doing array creation. By setting the largest array element ([3]) first, we preallocate the array to that size, putting 0's in all the other elements. If we were to set the elements in order, [0], [1], then [3], internally DAQFactory would be forced to reallocate three times which is much slower, especially when the arrays get large.
HexString(string, element size): converts a string in hexstring format to an array of numbers. Every two characters in the hexstring correspond to one byte. Element size determines the number of bytes in each number (i.e. 1 = byte, 2 = word, 4 = double word / long integer or float, etc). However, the numbers are not reassembled. Instead, if you specify an element size other than one, you will be returned a multidimensional array. You can then use one of the To. functions to convert that array into an array of numbers. The hex string is typically for use in setting/reading blob data in SQL statements.
From.HexString("FFFF7FFF0003", 2) returns {{255, 255}, {127, 255}, {0, 3}}
We can then convert that into the proper numbers using to.urWord():
To.urWord(From.HexString("FFFF7FFF0003", 2)) returns {65535, 32767, 3}
Comment: now you may wonder why the To and From functions take and return values in the second dimension. This is because the first dimension in DAQFactory always refers to values in time, and individual bytes or bits are all part of a single value at a single time. This becomes handy when you want to do something like plot the status of a certain bit of a channel over time. Lets say you want to plot bit 2:
Y Expression: (To.Bit(MyChannel,3))[][2]
Notice also in the above expression that we do ,3. This means that only up to the desired bit is converted saving memory. Of course the better way to retrieve a single bit is to use the TestBit function:
Y Expression: TestBit(MyChannel,3)
But if you wanted to sum the second and third bits for some reason...:
Y Expression: SumCols(To.Bit(MyChannel,3)[][1,2])
That all said, if you only want to convert to a single value with a To function (other then bit), or From.Bit, you can specify an array in the first dimension. So, To.Word({{0,128}}) is the same as To.Word({0,128}). Of course, when you are dealing with time, you have to follow the convention just described.