Home AMX User Forum NetLinx Studio
Options

Debugging incoming hex (or, 1-wire modules?)

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. :)

Comments

  • Options
    GSLogicGSLogic Posts: 562
    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.
  • Options
    samossamos Posts: 106
    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
  • Options
    amxhobbyistamxhobbyist Posts: 90
    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. :)
  • Options
    GSLogicGSLogic Posts: 562
    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
  • Options
    GSLogicGSLogic Posts: 562
    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!
  • Options
    Chip MoodyChip Moody Posts: 727
    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
  • Options
    amxhobbyistamxhobbyist Posts: 90
    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)
  • Options
    amxhobbyistamxhobbyist Posts: 90
    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.
  • Options
    alexanboalexanbo Posts: 282
    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...
    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.
  • Options
    Reese JacobsReese Jacobs Posts: 347
    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.
  • Options
    amxhobbyistamxhobbyist Posts: 90
    Wonderful! Huge thanks to both of you.
  • Options
    Reese JacobsReese Jacobs Posts: 347
    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
  • Options
    amxhobbyistamxhobbyist Posts: 90
    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. :)
  • Options
    Chip MoodyChip Moody Posts: 727
    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
  • Options
    amxhobbyistamxhobbyist Posts: 90
    Thanks Chip.
    Your code nukes the contents of the buffer two seconds after it gets a message - I'd question why
    Just for troubleshooting something else. :)

    Yes, GET_BUFFER_CHAR is what I wanted. Thank you!
    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?
    They appear to be all one character. So far all of the docs I've read deal with individual "packets" of one byte.

    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. :)
  • Options
    DanielDaniel Posts: 9
    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
  • Options
    Chip MoodyChip Moody Posts: 727
    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.
    Oh duh. I completely overlooked where the test was supposed to be on the last two bits, not the last BIT.

    But alexanbo didn't:
    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...
    So yeah, a better test would have been
    IF ((onewirebuffer[x] BAND $03) = $01)
    

    Thanks for pointing that out, Daniel...

    - Chip
Sign In or Register to comment.