Debugging incoming hex (or, 1-wire modules?)
amxhobbyist
Junior Member
I don't see that a 1-wire (iButton) Netlinx module exists, and thus am embarking on a task to write one for the Dallas DS9097U. If there is one already out there, please let me know where to find it so I can save myself a lot of pain. 
I write code a bit different; lots of trial and error, throwing commands at devices to see what they return in various circumstances, etc. It works for me.
The problem: Almost everything for this device is in hex, and it's impossible to determine what the interface is actually sending me (for troubleshooting purposes) because I don't know how to display it in a format I can read. (I'm currently pushing all incoming data to syslog so I can watch what happens when I throw various commands at it).
The question: How can I convert this data to something readable (hextoi doesn't seem to help at all, so I tried itoa the result of the hextoi and just get 0s)? Alternately, is there a good terminal emulator (for linux or windows) that will let me send hex & display incoming hex in a manner I can interpret?
I wrote some Axcess code to interface with a cm11a "activehome" X-10 interface a couple of years back. That was mostly hex as well, but it was straightforward: The device responded exactly as the documentation said it would. This one doesn't, so I need to see what it's really trying to tell me.
Thank you.
I write code a bit different; lots of trial and error, throwing commands at devices to see what they return in various circumstances, etc. It works for me.
The problem: Almost everything for this device is in hex, and it's impossible to determine what the interface is actually sending me (for troubleshooting purposes) because I don't know how to display it in a format I can read. (I'm currently pushing all incoming data to syslog so I can watch what happens when I throw various commands at it).
The question: How can I convert this data to something readable (hextoi doesn't seem to help at all, so I tried itoa the result of the hextoi and just get 0s)? Alternately, is there a good terminal emulator (for linux or windows) that will let me send hex & display incoming hex in a manner I can interpret?
I wrote some Axcess code to interface with a cm11a "activehome" X-10 interface a couple of years back. That was mostly hex as well, but it was straightforward: The device responded exactly as the documentation said it would. This one doesn't, so I need to see what it's really trying to tell me.
Thank you.
Comments
-
First you need to know what commands you are looking for from the device, HEX can be converted to integer, binary or ASCII.
Post a command from the data return of your device and also what you'd like it to be converted too. -
Look Rs232
This is a program that is a terminal emulator that lets you send and recieve ascii,hex,and other formats. You can search for a free download at google -
Gary,
Quick example: When a new device arrives on the bus, the unit is supposed to send XXXXXX01b, where the X's are undefined. It's sending something, since I get an entry in my syslog with extended ascii characters, but that doesn't help me in seeing what it actually sent back.
How do I search a hex string? I was using:
tmp = right_string (onewirebuffer,1)
if (tmp = "$1b") { // do something }
But this trigger isn't running. I'm guessing right_string doesn't work on hex data.
Steve,
Thank you for the info. That should help me query this device back and forth to see what it's really doing so I can write Netlinx code to talk to it.
-
Steve
The real world syntax for HEX is "0x00" not "$", this is a AMX thing.
If you are looking for HEX "0x1b", most devices retyrn it as "1B".
Example:
DATA.TEXT -
Steve
The real world syntax for HEX is "0x00" not "$", this is an AMX thing.
If you are looking for HEX "0x1b", most devices return it as '1B'.
Example:
DATA.TEXT[DEVICE??]
{
STRING:
{
IF(FIND_STRING(DATA.TEXT, '1b', 1))
//DO SOMETHING
}
}
Hope this helps! -
You could drop in a piece of code that takes whatever comes in the com port and sends out a readable representation to either the terminal window or to a telnet window with diagnostic messages activated.
DEFINE_FUNCTION DebugMsg (CHAR Msg[]) { LOCAL_VAR INTEGER x LOCAL_VAR INTEGER startbyte LOCAL_VAR CHAR debug[80] startbyte = 1 WHILE ((startbyte + 16) < LENGTH_STRING(Msg)) { debug = '$' FOR (x=0;x<15;x++) debug = "debug,RIGHT_STRING("'0',ITOHEX(Msg[startbyte+x])",2),',$'" debug = "debug,RIGHT_STRING("'0',ITOHEX(Msg[startbyte+x])",2)" SEND_STRING 0,debug startbyte = startbyte + 16 } IF (startbyte < LENGTH_STRING(Msg)) { debug = '$' FOR (x=startbyte;x<LENGTH_STRING(Msg);x++) debug = "debug,RIGHT_STRING("'0',ITOHEX(Msg[x])",2),',$'" debug = "debug,RIGHT_STRING("'0',ITOHEX(Msg[x])",2)" SEND_STRING 0,debug } }
- Chip -
Thanks for the code, Chip. It's helped somewhat, as I can now see the proper response from the unit when I issue a reset command. Unfortunately it doesn't seem to process the "new device on the bus" message right.
Quick example, I issue a reset pulse to the device with:
send string dev_rs232_1wire,"$00,$C1"
I get the following response in syslog:
May 4 19:57:44 ni3000 OneWireModule: Raw: ^A
May 4 19:57:44 ni3000 OneWireModule: itohex: 1
May 4 19:57:44 ni3000 OneWireModule: hextoi:
May 4 19:57:44 ni3000 OneWireModule: itoa: 1
May 4 19:57:44 ni3000 OneWireModule: Raw: ^A?
May 4 19:57:44 ni3000 OneWireModule: itohex: 1
May 4 19:57:44 ni3000 OneWireModule: hextoi:
May 4 19:57:44 ni3000 OneWireModule: itoa: 1
May 4 19:57:46 ni3000 OneWireModule: $01,$CD
May 4 19:57:46 ni3000 OneWireModule: cleared
The second to last line ($01,$CD) is from your debug code, and 0xCD is the appropriate response to a reset, so I've got that working. The entire response is generated with the following Netlinx code:data_event [dev_rs232_1wire] { string: { syslog(Info, 'OneWireModule', "'Raw: ',onewirebuffer") syslog(Info, 'OneWireModule', "'itohex: ',itohex(onewirebuffer)") syslog(Info, 'OneWireModule', "'hextoi: ',hextoi(onewirebuffer)") syslog(Info, 'OneWireModule', "'itoa: ',itoa(onewirebuffer)") wait 20 { DebugMsg(onewirebuffer) clear_buffer onewirebuffer syslog(Info, 'OneWireModule', "'cleared'") } } }(I wanted to run various conversions since I wasn't positive what the device would be spitting out during different operations)
Simple enough. Now, according to the manual for the chip inside the DS9097U, when a new device arrives on the 1-wire bus, "The DS2480B will recognize this unsolicited presence pulse and notify the host by sending a byte such as XXXXXX01b. The Xs represent undefined bit values. The fact that the host receives the byte unsolicited together with the pattern 01b in the least significant 2 bits marks the bus arrival."
When I add a device to the bus I get no response from your code. I simply get:
May 4 19:57:38 ni3000 OneWireModule: Raw: ?
May 4 19:57:38 ni3000 OneWireModule: itohex: CD
May 4 19:57:38 ni3000 OneWireModule: hextoi:
May 4 19:57:38 ni3000 OneWireModule: itoa: 205
May 4 19:57:40 ni3000 OneWireModule: cleared
So, I'm a bit stumped on how to proceed. Any advice would be greatly appreciated. (Also... when this code is finished & tested, I will release the module under the GPL for all to use) -
Gah, I'm getting closer to figuring this out. You can probably ignore the above; I was confusing bits and bytes - I'm receiving a byte successfully, but need to break it down into the 8 bits and analyze them.
I now have a more direct question: How do I do that?
Example: I receive the incoming byte 0xCD. I have to break that into it's binary value (11001101) and then check to see if the last two bits are 01. If so, I know a device has just arrived on the bus and I can therefore take action. -
Well i'm a little rough on the bitwise math but if you BAND it with binary 11 and it equals 1 then that should do it i think...amxhobbyist wrote:Gah, I'm getting closer to figuring this out. You can probably ignore the above; I was confusing bits and bytes - I'm receiving a byte successfully, but need to break it down into the 8 bits and analyze them.
I now have a more direct question: How do I do that?
Example: I receive the incoming byte 0xCD. I have to break that into it's binary value (11001101) and then check to see if the last two bits are 01. If so, I know a device has just arrived on the bus and I can therefore take action. -
Debugging incoming hex (or, 1-wire modules?)
As Alex said, BAND is one way to check the response from the device to see if specific flags are set. For instance, if cResponse below is a CHAR that represents a byte received from the device and you wish to check to see if the last 2 bits are 01, then do:IF(cResponse BAND $01) do something ...
You could alternately mask off all of the other bits and store the result and then do a simple test in the event you need to test this result more than once (such as storing the status for later use throughout a module):cResponse = cResponse BAND $01 IF(cResponse) do something ...
In addition to BAND, Netlinx supports BOR, BXOR, and BNOT bitwise operations as well as left and right shift operations. The negation operator (~) can be useful in bitwise operations also. If you wanted to check to see if any bits other than the last 2 bits in cResponse are set (as an example), you could do the following instead of creating the hex equivalent:IF(cResponse BAND ~($01)) // ~($01) = $FE = binary 11111110 do something ...
For other bit combinations, simply form the hex equivalent of the bit string you wish to check and the technique should work. Netlinx does not currently support a method of specifying constants in binary format as many languages do. This would be a nice addition to Netlinx/Studio as bitwise operations are common with certain device types and while converting binary to hex is not a tremendous challenge, having a binary constant format would be useful and could improve the self-documenting aspects of code that deals with bitwise operations. -
Wonderful! Huge thanks to both of you.
-
Debugging Incoming Hex (Code Sample Correction)
I wanted to correct something in my last post to make sure I don't totally confuse someone. In my last code sample, I was trying to illustrate that you could use the negation operator (~) to create a mask allowing you to check to see if any bits other than the last 2 bits were set. I inadvertantly used the wrong hex mask - here is the corrected code sample:IF(cResponse BAND ~($03)) // ~($03) = $FC hex = 11111100 binary do something ...
The original sample would have been fine for testing all bits except for the last 1 but was not correct for checking the last 2 bits. Sorry for any confusion.
Reese -
Two more questions:
1. The BAND doesn't seem to work:DEFINE_VARIABLE char onewirebuffer[1000] DEFINE_START create_buffer dev_rs232_1wire, onewirebuffer DEFINE_EVENT data_event [dev_rs232_1wire] { string: { syslog(Info, 'OneWireModule', "'itohex: ',itohex(onewirebuffer)") if (onewirebuffer BAND $01) { // new device arrived syslog(Info, 'OneWireModule', "'got 01'") } wait 20 { clear_buffer onewirebuffer syslog(Info, 'OneWireModule', "'cleared'") } } }
In syslog, I get:
May 8 20:34:30 ni3000 OneWireModule: itohex: CD
May 8 20:34:32 ni3000 OneWireModule: cleared
So the BAND isn't matching. But 0xCD is 11001101, which means the BAND should work, right? Do I need to break onewirebuffer down somehow? I do get a warning, "C10571: Converting type [string] to [CHAR]", on compile.
2. How can I break onewirebuffer down into individual bits and/or bytes? Data is going to be streaming at this thing and any individual "string:" event may contain several bytes that need to be looked at individually. In another module I wrote, I had an incoming pattern to work with so I built a queue and processed it with "remove_string". Can I do something similar with an individual bit and/or byte?
Working on the bit level is new to me, not just within Netlinx, so I'm having to learn as I go. The last time I got this close to a device I only had to deal with full bytes.
But I'm making a lot of progress thanks to you folks.
Really I'm surprised a 1-wire module doesn't already exist. If you've never worked with 1-wire devices, you owe it to yourself to try. Really nice for access control (iButtons) and temperature sensing applications, and absolutely dirt cheap. Hopefully I'll have a basic module released soon.
-
AHG,
In your comparison, you're trying to take a potentially multiple character string and comparing it to a single character. You'd probably want to do something like this instead:FOR (x=1;x<=LENGTH_STRING(onewirebuffer);x++) { IF (onewirebuffer[x] BAND $01) { // do some stuff } }
If the message that comes in is one or more bytes, all of them will get checked.
Your code nukes the contents of the buffer two seconds after it gets a message - I'd question why, but I'll save that for a different discussion.
With that code in place, the above example would re-examine contents of onewirebuffer if more than one string comes in during a two second time period. (Which could happen if you get a string in that's larger than your processor's 232 hardware buffer, or if there's any kind of pause in the incoming message, or if the device simply generates more than one message in that time period)
REMOVE_STRING is great and is very helpful IF you already know the characters you want to remove up to in a string. You may have been thinking of GET_BUFFER_CHAR? That would have gone like this:WHILE (LENGTH_STRING(onewirebuffer)) { IF (GET_BUFFER_CHAR(onewirebuffer) BAND $01) { // do some stuff } }
Chances are that you could get messages larger than one character in, so that method probably won't help you much as it destroys the contents of the buffer as it goes.
So this iButton stuff - are all the messges 1 character, all the time? If not, how are you supposed to tell the difference between the "online" message and any other?
- Chip -
Thanks Chip.
Just for troubleshooting something else.Your code nukes the contents of the buffer two seconds after it gets a message - I'd question why
Yes, GET_BUFFER_CHAR is what I wanted. Thank you!
They appear to be all one character. So far all of the docs I've read deal with individual "packets" of one byte.So this iButton stuff - are all the messges 1 character, all the time? If not, how are you supposed to tell the difference between the "online" message and any other?
The "online" message is recognized because it is (a) unsolicited, and (b) has "the pattern 01b in the least significant 2 bits" according to the docs. All other 1-wire operations originate from the host (such as reading the value of a tempreature sensor, reading/writing to a crypto ibutton, etc). So when you use an iButton for access control use, you press the button against a contact pad. It is recognized, a "new device online" message is sent, you search the bus for the new device during which you obtain it's unique 64 bit ID. That is compared against a list of valid IDs and, if valid, you perform some action.
It's not an incredibly complicated system, once you know how to play with bits in the programming langauge you're using.
-
BAND $01 confusion
The problem with the If( nResponse BAND $01 ) condition is that it will be true if the last 2 bits of nResponse are 01 or 11, so wrong half the time if you are specifically looking for 01.
The correct statment should be:
if( ( nResponse BAND 1 ) and !( nResponse BAND 2 ) )
{
do something
}
The second part of the statement makes sure that the 2nd bit isn't a 1.
2 is 10 in binary.
11 BAND 10 = 10
NOT 10 = 0 ( NOT anything else than 0 will equal 0 )
01 BAND 10 = 00
NOT 00 = 1
by the way, writting $01 or 1 is the same, from 0 to 9...
I hope this helps...
D -
Oh duh. I completely overlooked where the test was supposed to be on the last two bits, not the last BIT.Daniel wrote:The problem with the If( nResponse BAND $01 ) condition is that it will be true if the last 2 bits of nResponse are 01 or 11, so wrong half the time if you are specifically looking for 01.
But alexanbo didn't:
So yeah, a better test would have beenWell i'm a little rough on the bitwise math but if you BAND it with binary 11 and it equals 1 then that should do it i think...IF ((onewirebuffer[x] BAND $03) = $01)
Thanks for pointing that out, Daniel...
- Chip
Categories
- All Categories
- 2.5K AMX General Discussion
- 922 AMX Technical Discussion
- 514 AMX Hardware
- 502 AMX Control Products
- 3 AMX Video Distribution Products
- 9 AMX Networked AV (SVSI) Products
- AMX Workspace & Collaboration Products
- 3.4K AMX Software
- 151 AMX Resource Management Suite Software
- 386 AMX Design Tools
- 2.4K NetLinx Studio
- 135 Duet/Cafe Duet
- 248 NetLinx Modules & Duet Modules
- 57 AMX RPM Forum
- 228 MODPEDIA - The Public Repository of Modules for Everyone
- 943 AMX Specialty Forums
- 2.6K AMXForums Archive
- 2.6K AMXForums Archive Threads
- 1.5K AMX Hardware
- 432 AMX Applications and Solutions
- 249 Residential Forum
- 182 Tips and Tricks
- 146 AMX Website/Forums