Your Universal Remote Control Center
RemoteCentral.com
Philips Pronto Professional Forum - View Post
Previous section Next section Previous page Next page Up level
Up level
The following page was printed from RemoteCentral.com:

Login:
Pass:
 
 

Page 1 of 2
Topic:
Hexadecimal string conversion for a RS 232 command
This thread has 23 replies. Displaying posts 1 through 15.
Post 1 made on Monday June 23, 2008 at 17:26
Ericbal
Long Time Member
Joined:
Posts:
December 2007
59
Hi,

I am trying to send the following command (RS-232)

"\xF0\x00\x00\x7F\x00\x00\x70\x05\x02\x02\x00\x00\xF1\x21\x00" + volume1 + "x00\x00\x00\x01" + (chk) + "\xF7"

where

- volume1 is a variable that contains a decimal value of room 1 volume
- chk is a checksum calculation

chk calculation is as follows:

chk = 0xF0 + 0x00 + 0x00 + 0x7F + 0x00 + 0x00 + 0x70 + 0x05 + 0x02 + 0x02 + 0x00 + 0x00 + 0xF1 + 0x21 + 0x00 + volume1 + 0x00 + 0x00 + 0x00 + 0x01 + 20;
chk = chk & 0x7F;

When a make the calculation manually, I get a different result than the one I obtain through my script (and displayed thanks to a System.print(chk) command).

I also tried with a (volume1).toString(16) conversion, but result is still not correct.

If I take the example of a volume1 = 13 (decimal), I should have at the end the following RS 232 command:

\xF0\x00\x00\x7F\x00\x00\x70\x05\x02\x02\x00\x00\xF1\x21\x00\x0D\x00\x00\x00\x01\x1C\xF7

ie volume1 = 13 (decimal) = D (hexadecimal)
and chk = 1C

Do you have any idea of how to handle this problem. I guess I have a variable convertion type problem, but I can't figure it out.

Thanks.

Eric.
Post 2 made on Monday June 23, 2008 at 22:12
Barry Gordon
Founding Member
Joined:
Posts:
August 2001
2,157
I do not compute 1C as the checksum when volume1 is 13 decimal. I get 776 in decimal, 308 hex which as a single byte of 8 bits is 08 in hex

without the volume value the string sums to 763 decimal or 2FB in hex taking the low order we get FB if we add 0D we get 08 in hex or 776 in decimal

You may have a mistake in your computation
Post 3 made on Tuesday June 24, 2008 at 01:08
buzz
Super Member
Joined:
Posts:
May 2003
4,380
I agree with Barry's computation: 308 (hex), yielding a checksum of "08" (hex).
OP | Post 4 made on Tuesday June 24, 2008 at 17:12
Ericbal
Long Time Member
Joined:
Posts:
December 2007
59
Thanks for your answers. I guess I was not clear enough in my previous post:

I agree with you that chk value is 776 decimal, 308 hexadecimal.

chk = 0xF0 + 0x00 + 0x00 + 0x7F + 0x00 + 0x00 + 0x70 + 0x05 + 0x02 + 0x02 + 0x00 + 0x00 + 0xF1 + 0x21 + 0x00 + volume1 + 0x00 + 0x00 + 0x00 + 0x01 + 20;

Then chk needs to be "and-ed" with 7F

chk = chk & 0x7F

I then get chk = 1C (hexadecimal)

I succeded in having this on my debug window by converting "and-ing" result to hexadecimal with:

chk = (chk & 0x7F).toString(16);

I then get stucked when trying to generate the correct RS-232 to be sent:

I use the following formula:

var command = "\xF0\x00\x00\x7F\x00\x00\x70\x05\x02\x02\x00\x00\xF1\x21\x00" + (volume1).toString(16) + "x00\x00\x00\x01" + (chk).toString(16) + "\xF7";

But it seems that I do not generate the correct RS 232 command as I get no result from my Russound CAM.

I cannot either see what command I generate because when I send a System.print (command) I only see in the debug panel a very weird sign that must be part of the decimal / hexadecimal table.
Post 5 made on Tuesday June 24, 2008 at 18:03
Barry Gordon
Founding Member
Joined:
Posts:
August 2001
2,157
Sorry 308hex anded with 7Fhex is 08hex. The anding operation reduces the chk value to a 7 bit (least significant 7 bits) value.

308hex and 7Fhex is 08hex not 1Chex.

if you want to do the and operation in decimal then 776 and 127 should produce the same value 08 since 08 decimal is 08 hex.

Remember, and is bit wise and in the binary number system

You might find this function helpful for debugging:

function showHEX(a)
{
var b=""; var i=0;
for(i=0; ireturn b;
}

use it as System.print(showHEX(anystring));

It will show you the hex character representation of the string

Last edited by Barry Gordon on June 24, 2008 18:13.
OP | Post 6 made on Thursday June 26, 2008 at 17:21
Ericbal
Long Time Member
Joined:
Posts:
December 2007
59
Thanks Barry,

Once again, I made a mistake and I mislead you...
The chk variable is summed with 20 (decimal). Result is then 31C which, anded with 7F gives 1C.

Question: is this formula correctly written ?

var command = "\xF0\x00\x00\x7F\x00\x00\x70\x05\x02\x02\x00\x00\xF1\x21\x00" + (volume1).toString(16) + "x00\x00\x00\x01" + (chk).toString(16) + "\xF7";

If it is, I should get for a volume1=13 (dec) or D (hex):

\xF0\x00\x00\x7F\x00\x00\x70\x05\x02\x02\x00\x00\xF1\x21\x00\x0D\x00\x00\x00\x01\x1C\xF7

and it is not the case.....

PS:
Is there not any error in the debugging function you sent ?

function showHEX(a)
{
var b=""; var i=0;
for(i=0; ireturn b;
}


Thanks.

Eric.
Post 7 made on Thursday June 26, 2008 at 17:28
Barry Gordon
Founding Member
Joined:
Posts:
August 2001
2,157
Damm, I didn't look at it closely and the marvelous HTML editor screwed it all up.

here it is correctly:

function showHEX(a) { var b=""; var i=0; for(i=0; i < a.length; i++) { b+=a.charCodeAt(i).toString(16); }; return b; }

Now why is the chk variable summed with decimal 20? I do agree if you sum the chk variable with 20 decimal you do get 31C (Hex 308 +14 hex = 31C hex) anded with 7F hex yields 1C.
OP | Post 8 made on Thursday June 26, 2008 at 17:35
Ericbal
Long Time Member
Joined:
Posts:
December 2007
59
Tks for the function,

I now see what is my command variable about....
OP | Post 9 made on Friday June 27, 2008 at 16:59
Ericbal
Long Time Member
Joined:
Posts:
December 2007
59
Hi,

I am getting mad with this matter...

To put it simple:

I have a variable called volume1 that contains volume level.

I want to send a command that is a combination of 2 fixed hexadecimal caracters and, in the middle, the hexadecimal value of the volume1 variable.

var command = "\xF0"+(volume1).toString(16)+"\xF7";

When I am using your showHEX(command) function, why do I get as a result F064F7 instead of F0DF7 for a volume1 value = 13 (decimal) = D (hexadecimal) ?

Thanks.
Post 10 made on Friday June 27, 2008 at 18:12
Barry Gordon
Founding Member
Joined:
Posts:
August 2001
2,157
well first of all F0DF7 has an odd number of characters so it can not possibly be a legal hex sequence I will assume you meant F00DF7. In a hex sequence every 8 bit character shows as two hex digits.

All I can say is that the value in volume1 is not what you think it is. If the function shows 64 then it is seeing the byte (8 bit character) as the decimal number 6*16 +4 which is the decimal value 100.

I also find it surprising that the device protocol would allow there to be a carriage return in the middle of a sequence. I suspect what it wants to see might be F03133F7 as the hex sequence for a volume value of 13. In that sequence 31 is the hex sequence for a "1" and 33 is the hex sequence for a "3". In almost all of the protocols I see that is the way numeric values are represented. This limits the data to what is commonly called the Latin-1 set of characters, those with the decimal codes of 32 (space) to 127. In many protocols characters below 32 decimal and above 127 are used for control purposes.

I do know of one protocol, the one used by iSacn for the DVDO line of video processors that allows both binary and Hex representations. the trouble with allowing binary for data in the range 0-255 (all possible bytes) is the aliasing to control characters. For that reason most protocols want to see numbers as I have shown them 13=3133, 100=313030, etc.

If I am correct in the above re the representation of numbers then the checksum needs to include (for the case of 13 decimal) the sums of hex characters 31 and 33 which turn out to be decimal 49 and 51 for 31 and 33 hex respectively

Last edited by Barry Gordon on June 27, 2008 18:27.
OP | Post 11 made on Sunday June 29, 2008 at 05:30
Ericbal
Long Time Member
Joined:
Posts:
December 2007
59
Thanks Barry,

The device I am controlling (or at least trying to...) is Russound CAM. What the RS 232 Russound protocol description says is:

"...These Volume levels are represented in Decimal when using RS-232 messages ranging in value from 0-50 (ie 0=0; 1=2,..., 2=4). In the actual Data messge the HEX value is used which would range in value from 0x00 - 0x32. This means (0x00 = 0, 0x01 = 1, 0x02=2=4, ..., 0x32=50=100).

The set volume message is

Byte 1 = F0
Byte 2 = 00 (controller number - 1)
Byte 3 = 00
Byte 4 = 7F
Byte 5 = 00
Byte 6 = 00
Byte 7 = 70
Byte 8 = 05
Byte 9 = 02
Byte 10 = 02
Byte 11 = 00
Byte 12 = 00
Byte 13 = F1
Byte 14 = 21
Byte 15 = 00
Byte 16 = volume level as decribed above
Byte 17 = 00
Byte 18 = 00 (zone number -1)
Byte 19 = 00
Byte 20 = 01
Byte 21 = checksum
Byte 22 = F7"


The strange thing is that the following command (with 0D in byte 16) is working and effectively sets the volume of zone 1 to 26 (13*2).

s.send("\xF0\x00\x00\x7F\x00\x00\x70\x05\x02\x02\x00\x00\xF1\x21\x00\x0D\x00\x00\x00\x01\x1C\xF7");

All what the function I am working on is about is to generate this type of command with variable content for byte 16 (volume) and byte 21 (checksum). Taken individually, the calculation of volume and checksum gives me the correct hex value,
but the concatenation in the following formula

var command = "\xF0\x00\x00\x7F\x00\x00\x70\x05\x02\x02\x00\x00\xF1\x21\x00" + (volume1/2).toString(16) + "\x00\x00\x00\x01" + chk.toString(16) + "\xF7";

is not giving me (for the example of volume1=26; volume1/2=13)

"\xF0\x00\x00\x7F\x00\x00\x70\x05\x02\x02\x00\x00\xF1\x21\x00\x0D\x00\x00\x00\x01\x1C\xF7"
Post 12 made on Sunday June 29, 2008 at 09:58
Barry Gordon
Founding Member
Joined:
Posts:
August 2001
2,157
I just pulled and glanced at the CAM RS232 spec. Yes they do send binary values. They use only three characters for transmission control (F0, F1, F7). The check sum includes a byte count.

First off, the version of ShowHex I published above leaves a lot to be desired (I must be getting very old)

Here is a proper version:

function ShowHEX(a) { var b=""; var c=""; var i=0; for(i=0; i < a.length; i++)
{ if(a.charCodeAt(i).toString(16).length==1)
b+="0"+a.charCodeAt(i).toString(16).toUpperCase()+" ";
else b+=a.charCodeAt(i).toString(16).toUpperCase()+" ";}
return b; }

In summary, what I think you are having trouble with is the code:

volume1=26; chk=28; // 28 decimal =1C hex
"\xF0\x00\x00\x7F\x00\x00\x70\x05\x02\x02\x00\x00\xF1\x21\x00" + (volume1/2).toString(16) + "\x00\x00\x00\x01" + chk.toString(16) + "\xF7";

I ran the following code:

var volume1=26; var chk=28; // 28 decimal =1C hex
var testcase="\xF0\x00\x00\x7F\x00\x00\x70\x05\x02\x02\x00\x00\xF1\x21\x00" + (volume1/2).toString(16) + "\x00\x00\x00\x01" + chk.toString(16) + "\xF7";
System.print("testcase="+ShowHEX(testcase))
stop

What I get on my debug display is:

testcase=F0 00 00 7F 00 00 70 05 02 02 00 00 F1 21 00 64 00 00 00 01 31 63 F7
ProntoScript error: ReferenceError: stop is not defined
Offending activity script: Tag: 'SSActivity'
Offending line #11: "stop"

I then decided to just skin the cat.

var chr=new Array()
chr=["\x00", "\x01", "\x02", "\x03", "\x04", "\x05", "\x06", "\x07", "\x08", "\x09", "\x0A", "\x0B", "\x0C", "\x0D", "\x0E", "\x0F",
"\x10", "\x11", "\x12", "\x13", "\x14", "\x15", "\x16", "\x17", "\x18", "\x19", "\x1A", "\x1B", "\x1C", "\x1D", "\x1E", "\x1F",
"\x20", "\x21", "\x22", "\x23", "\x24", "\x25", "\x26", "\x27", "\x28", "\x29", "\x2A", "\x2B", "\x2C", "\x2D", "\x2E", "\x2F",
"\x30", "\x31", "\x32", "\x33", "\x34", "\x35", "\x36", "\x37", "\x38", "\x39", "\x3A", "\x3B", "\x3C", "\x3D", "\x3E", "\x3F",
"\x40", "\x41", "\x42", "\x43", "\x44", "\x45", "\x46", "\x47", "\x48", "\x49", "\x4A", "\x4B", "\x4C", "\x4D", "\x4E", "\x4F",
"\x50", "\x51", "\x52", "\x53", "\x54", "\x55", "\x56", "\x57", "\x58", "\x59", "\x5A", "\x5B", "\x5C", "\x5D", "\x5E", "\x5F",
"\x60", "\x61", "\x62", "\x63", "\x64", "\x65", "\x66", "\x67", "\x68", "\x69", "\x6A", "\x6B", "\x6C", "\x6D", "\x6E", "\x6F",
"\x70", "\x71", "\x72", "\x73", "\x74", "\x75", "\x76", "\x77", "\x78", "\x79", "\x7A", "\x7B", "\x7C", "\x7D", "\x7E", "\x7F"]


and ran the following code:

var volume1=26; var chk=28; // 28 decimal =1C hex
var testcase="\xF0\x00\x00\x7F\x00\x00\x70\x05\x02\x02\x00\x00\xF1\x21\x00" + chr[volume1/2] + "\x00\x00\x00\x01" + chr[chk] + "\xF7";
System.print("Hex="+ShowHEX(testcase))
stop

Producing the following:

Hex=F0 00 00 7F 00 00 70 05 02 02 00 00 F1 21 00 0D 00 00 00 01 1C F7 ProntoScript error: ReferenceError: stop is not defined
Offending activity script: Tag: 'SSActivity'
Offending line #28: "stop"


Which I believe is what you want.


Javascript definately has issues dealing and representing basic character codes and converting numbers to pure characters.

for example var a=13; a.toString16() does produce the letter d but as a string. the ordinal code for the letter d in ASCII is 100 so what actually ends up in the byte is the decimal integer 100 which has the hex value of 64. That is why showHEX shows it as 64. if you do a=28, a.tostring(16) what you get is the sequence 1C as a string which is stored as two bytes "1" "c" which have ordinal ascii code values of 49 and 63 which showHEX properly shows as 31 63. if you try a=13; "0x"+a.toString(16) you get 3 bytes "0","x","d".

The chr array as shown above will properly handle any integer in the range 0-127 and could be expanded to handle 0-255 and automatically add the needed F1 code and the inverted value (as required by the Russound protocol) to produce values in the range 128-255. I leave that as an exercise to the reader.

I hope this helps you resolve your problem. Feel free to use the chr array and be sure to update the ShowHEX function if you are using it.

Last edited by Barry Gordon on June 29, 2008 10:05.
Post 13 made on Sunday June 29, 2008 at 12:55
Lyndel McGee
RC Moderator
Joined:
Posts:
August 2001
12,999
Barry's example will likely work with no problems but there is likely a simpler way to do
this. (Barry, I'm sure will correct me if I am dead wrong here).

After all this, I believe the root of the problem to be:

The problem is how to "encode" various bytes from programmatic values into an ASCII string.

128.toString(16) will generate a string with value "80", not the '\x80' which is actually 1 byte of ASCII value 128.

You actually want the 2nd form.

To do this, use String.fromCharCode(somevalue & 0xff);

So for the 3 bytes below (from your example above and assuming you already know how to build volume string) try this. Note that the code below cannot be run as-is but intended to be used as an example of "how" to build the proper strings.

var Byte2 = String.fromCharCode((controllernumber - 1) & 0xff);
var Byte18 = String.fromCharCode((zonenumber - 1) & 0xff);
var Byte21 = String.fromCharCode(checksum & 0xff);
Lyndel McGee
Philips Pronto Addict/Beta Tester
Post 14 made on Sunday June 29, 2008 at 13:31
Barry Gordon
Founding Member
Joined:
Posts:
August 2001
2,157
Yes Lyndels solution should work just as well. I am posting the table look up solution since it should be the fastest method as it should compile to direct code with no function invocation. I am posting it with the correct array for all 256 values and the correct array for the Russound protocol which requires special treatment for integers between 128 and 255 inclusive

Last edited by Barry Gordon on June 29, 2008 18:29.
OP | Post 15 made on Sunday June 29, 2008 at 17:39
Ericbal
Long Time Member
Joined:
Posts:
December 2007
59
Barry,

You are Magic !

The "array with hex values" approach works !

I will now implement this in all my volume functions.

Thanks you very much.

Eric.
Page 1 of 2


Jump to


Protected Feature Before you can reply to a message...
You must first register for a Remote Central user account - it's fast and free! Or, if you already have an account, please login now.

Please read the following: Unsolicited commercial advertisements are absolutely not permitted on this forum. Other private buy & sell messages should be posted to our Marketplace. For information on how to advertise your service or product click here. Remote Central reserves the right to remove or modify any post that is deemed inappropriate.

Hosting Services by ipHouse