Home AMX User Forum NetLinx Studio

HEX Reader

I am trying to fault find a device attached to an NI-3000 and the device uses HEX strings to communicate. I have been logging all communications to a file and notepad will not read the hex codes in the file (?? Q).

Do any of you use any HEX readers that you could recomend ?

Comments

  • Do you know if it is possible to decode the HEX to ASCII within the AMX and then save it to file in a viewing friendly format like the notifications window ?
  • Joe HebertJoe Hebert Posts: 2,159
    If you are logging the raw data to a file, you can get a friendly view with the free hex viewer/editor program that I linked above. Or if you want to create your own friendly file you can use the ITOHEX() or FORMAT() functions when writing the data to disk. Or am I completely missing your question?
  • Thanks, I did take a look at the viewer but not sure it?s what I need.

    The device I am logging has no fixed end of line or beginning of line characters and occasionally it varies in length. When writing to the log file I add a time to the start of the line to allow me to easily see when the command was sent and it also helps divides the log file up a bit so I can quickly find the information and see patterns.

    When I use the HEX viewer it has no structure to how it is viewed and justs wraps it in fixed widths presenting a window full of HEX. It would help if I could identify a set of characters as EOL markers or split it out into blocks, which I would match up to my date stamps to help break the view up, but I?m not sure if that?s possible.

    I then thought it may be easier to decode the HEX and write the logs files in ASCII, then I could present them how I wanted and view then in notepad.
    e.g.
    <date>: $01,$02,$05
    <date>: $03,$02,$05,$02,$05
  • Joe HebertJoe Hebert Posts: 2,159
    How about something like this:
    DEFINE_DEVICE
    
    dvTP	= 10001:1:0
    
    DEFINE_VARIABLE
    
    CHAR	cTestData[] = {1,2,5,10,255}
    
    DEFINE_FUNCTION fnMakeThisFriendly(char instring[]) {
    
       CHAR	 	outstring[128]
       INTEGER 	x
       
       FOR (x=1; x<=LENGTH_ARRAY(instring); x++) {
          outstring = "outstring,'$',FORMAT('%02X',instring[x]),$20"
       }
       
       outstring = "DATE,':',$20,outstring"
    
       //replace this with file write routine
       SEND_STRING 0, outstring
    }
    
    DEFINE_EVENT
    
    BUTTON_EVENT[dvTP,1] {
    
       PUSH: {
          fnMakeThisFriendly(cTestData)
       }
    }
    
    Here is the output when button 1 is pushed:

    Line 1 :: 09/28/07: $01 $02 $05 $0A $FF - 02:18:50
  • Thanks for this it's perfect. I have never used the format command before, it looks very useful.

    Cheers
  • Joe HebertJoe Hebert Posts: 2,159
    Format()

    Glad to help. FORMAT() is the super-duper big brother/cousin of ITOA() and is extremely useful indeed.

    Cheers.
  • Joe HebertJoe Hebert Posts: 2,159
    Oops

    This line works fine:
    outstring = "outstring,'$',FORMAT('%02X',instring[x]),$20"

    But I should have wrote it this way instead:
    outstring = "outstring,FORMAT('$%02X',instring[x]),$20"
  • AMXJeffAMXJeff Posts: 450
    debug.axi

    Alot of people don't know, but there is actually a debug.axi include file that is installed with studio.

    see the include file below. It contains alot of x to string conversation for sending to terminal.

    C:\Program Files\Common Files\AMXShare\AXIs\debug.axi
    PROGRAM_NAME='debug'
    (***********************************************************)
    (*  FILE CREATED ON: 12/28/2001 AT: 00:00:00               *)
    (***********************************************************)
    (*  FILE_LAST_MODIFIED_ON: 06/30/2006  AT: 16:06:33        *)
    (***********************************************************)
    (*  FILE REVISION: Rev 2.04 GLM                            *)
    (*  REVISION DATE: 06/30/2006  AT: 16:06:33                *)
    (*      - 'SEND DEVICE_INFO TO DEBUG' now trims garbage    *)
    (*        from SN's less than 16 characters long.          *)
    (***********************************************************)
    (*  FILE REVISION: Rev 2.03 GLM                            *)
    (*  REVISION DATE: 07/08/2005  AT: 15:12:54                *)
    (*      - All "DEV..." functions now return the actual     *)
    (*        system number, never 0...                        *)
    (***********************************************************)
    (*!!FILE REVISION: 2.02 GLM                                *)
    (*  REVISION DATE: 05/31/2005                              *)
    (*      - In the 'SEND...' calls, replace STR1 with an     *)
    (*        equal number of spaces if a single reply takes   *)
    (*        more than one line, after the first line.        *)
    (*        So it's easier to distiguish between multiple    *)
    (*        responses.                                       *)
    (***********************************************************)
    (*!!FILE REVISION: 2.01 GLM                                *)
    (*  REVISION DATE: 02/01/2005                              *)
    (*      - added DPS_TO_STRING, similar to DEV_TO_STRING    *)
    (*        but always returns actual system number.         *)
    (*      - added 'STRING TO DEV' call. A call because       *)
    (*        functions cannot return complex data types such  *)
    (*        as DEVs.                                         *)
    (*      - fixed problem where sometimes an extra ' would   *)
    (*        sneak into 'SEND 7BIT ASCII TO DEBUG' responses. *)  
    (*      - 'SEND ASCII TO DEBUG' and 'SEND ASCII TO MASTER' *)
    (*        now format DEL as $7F.                           *)
    (*      - changed the 'SEND...' calls so they no longer    *)
    (*        add a space between the header and data.         *) 
    (*      - added 'SEND DEVICE_INFO TO DEBUG'.               *)  
    (*      - rearranged calls alphabetically.                 *)
    (***********************************************************)
    (*!!FILE REVISION: 2.00 GLM                                *)
    (*  REVISION DATE: 11/22/2004                              *)
    (*      - use STACK_VAR instead of LOCAL_VAR.			   *)
    (*      - no longer has virtual device for control, it was *)
    (*        never used in practice.                          *)
    (***********************************************************)
    (*!!FILE REVISION: 1.07 GLM                                *)
    (*  REVISION DATE: 04/22/2004                              *)
    (*      - added DEV_CHAN_TO_STRING, DEV_LEV_TO_STRING      *)
    (*        these functions take a seperate dev,chan or      *)
    (*        dev,lev as parameters.                           *)
    (***********************************************************)
    (*!!FILE REVISION: 1.06 GLM                                *)
    (*  REVISION DATE: 09/15/2003                              *)
    (*      - modified 'SEND INTEGER TO DEBUG' to only format  *)
    (*        line length. It had been a misnamed version of   *)
    (*        'SEND DECIMAL TO DEBUG'.                         *)
    (***********************************************************)
    (*!!FILE REVISION: 1.05 GLM                                *)
    (*  REVISION DATE: 05/29/2003                              *)
    (*      - added 'SEND 7BIT ASCII TO DEBUG'                 *)
    (*        characters  >= $7F are formated as hex           *)
    (*      - remove ; from #DEFINE __DEBUG_LIB__              *)
    (*      - added explicit parameter types where missing     *)
    (*      - added 'SEND DECIMAL TO DEBUG'. This is actually  *)
    (*        what 'SEND INTEGER TO DEBUG' should have been    *)
    (*        named.                                           *)
    (***********************************************************)
    (*!!FILE REVISION: 1.04 GLM                                *)
    (*  REVISION DATE: 01/21/2003                              *)
    (*      - added 'SEND INTEGER TO DEBUG'                    *) 
    (***********************************************************)
    (*!!FILE REVISION: 1.03 GLM                                *)
    (*  REVISION DATE: 08/28/2002                              *)
    (*      Code cleanup:                                      *)
    (*      - added line ends ";" for Studio debug mode.       *)
    (*      - changed remaining LENGTH_STRING's to             *)
    (*        LENGTH_ARRAY's.                                  *)
    (*      - explicitly declare all variable types.           *) 
    (***********************************************************)
    (*!!FILE REVISION: 1.02 GLM                                *)
    (*  REVISION DATE: 04/27/2002                              *)
    (*      - Added 'SEND ASCII TO DEBUG' and 'SEND ITOHEX TO  *)
    (*        DEBUG'.                                          *)
    (*        These calls have:                                *)
    (*        - Device parameter to allow sending info to      *)
    (*        devices other than 0:0:0, for example to virtual *)
    (*        device for multi master debugging.               *) 
    (*        - Line length parameter to allow different line  *)
    (*        lengths. If this is 0, line length defaults to   *)
    (*        80 for mode  2, 67 for all other modes           *) 
    (*        - Mode parameter, if set to 2 appends <cr>,<lf>  *)
    (*        to each line for master 'MSG ON 2'               *)
    (*!!FILE REVISION: 1.01 GLM                                *)
    (*  REVISION DATE: 04/27/2002                              *)
    (*      - First line returned by the 'SEND ASCII...' and   *)
    (*        'SEND ITOHEX...' calls is one less character     *)
    (*        than subsequent lines to account for Netlinx '>' *)
    (*        prompt. Removed in version 1.02.                 *)
    (***********************************************************)
    (*!!FILE REVISION: 1.00 GLM                                *)
    (*  REVISION DATE: 03/26/2002                              *)
    (*                                                         *)
    (*  COMMENTS:                                              *)
    (* DEBUG FUNCTIONS AND CALLS                               *)
    /*  1   FUNCTION CHAR[17] DEV_TO_STRING (DEV dvDEV)                           */
    /*  2   FUNCTION CHAR[25] DEVCHAN_TO_STRING (DEVCHAN dcDC)                    */
    /*  3   FUNCTION CHAR[25] DEV_CHAN_TO_STRING (DEV dvDEV, INTEGER nCH)         */
    /*  4   FUNCTION CHAR[25] DEVLEV_TO_STRING (DEVLEV dlDL)                      */
    /*  5   FUNCTION CHAR[25] DEV_LEV_TO_STRING (DEV dvDEV, INTEGER nLV)          */
    /*  6   FUNCTION CHAR[17] DPS_TO_STRING (DEV dvDEV)                           */
    /*  7   CALL 'SEND 131 BYTE PACKETS TO MASTER' (sSTRING[])                    */
    /*  8   CALL 'SEND 7BIT ASCII TO DEBUG' (DEV dvDEBUG,STR1[],STR2[],nLine,nMode)*/
    /*  9   CALL 'SEND ASCII TO DEBUG' (DEV dvDEBUG,STR1[],STR2[],nLine,nMode)    */
    /* 10   CALL 'SEND ASCII TO MASTER' (STR1[],STR2[])                           */
    /* 11   CALL 'SEND DECIMAL TO DEBUG' (DEV dvDEBUG,STR1[],STR2[],nLine,nMode)  */
    /* 12   CALL 'SEND DEVICE_INFO TO DEBUG' (DEV dvDEBUG, DEV dvDEV)             */
    /* 13   CALL 'SEND INTEGER TO DEBUG' (DEV dvDEBUG,STR1[],STR2[],nLine,nMode)  */
    /* 14   CALL 'SEND ITOHEX TO DEBUG' (DEV dvDEBUG,STR1[],STR2[],nLine,nMode)   */
    /* 15   CALL 'SEND ITOHEX TO MASTER' (STR1[],STR2[])                          */
    /* 16   CALL 'STRING TO DEV' (sDEV[],dvDEV)                                   */
    (***********************************************************)
    #IF_NOT_DEFINED __DEBUG_LIB__
    #DEFINE __DEBUG_LIB__
    (***********************************************************)
    (*          DEVICE NUMBER DEFINITIONS GO BELOW             *)
    (***********************************************************)
    DEFINE_DEVICE
    
    (***********************************************************)
    (*               CONSTANT DEFINITIONS GO BELOW             *)
    (***********************************************************)
    DEFINE_CONSTANT
    
    // VERSION FOR CODE 
    
    CHAR __DEBUG_LIB_NAME__[12]     = '   debug.axi';
    CHAR __DEBUG_LIB_VERSION__[]    = '2.04';
    
    CHAR __SPACES__[128] = 
    {
      $20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,
      $20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,
      $20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,
      $20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,
      $20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,
      $20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,
      $20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,
      $20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20
    }
    
    (***********************************************************)
    (*           SUBROUTINE DEFINITIONS GO BELOW               *)
    (***********************************************************)
    (* EXAMPLE: DEFINE_FUNCTION <RETURN_TYPE> <NAME> (<PARAMETERS>) *)
    (* EXAMPLE: DEFINE_CALL '<NAME>' (<PARAMETERS>) *)
    
                                        ///////////////////////////  
                                        // DEBUG FUNCTIONS/CALLS //
                                        ///////////////////////////  
    // DEFINE_FUNCTION DEV_TO_STRING
    // PARAMETER: 
    // dvDEV - DEVICE USED
    // RETURNS:
    // dvDEV AS A STRING
    DEFINE_FUNCTION CHAR[17] DEV_TO_STRING (DEV dvDEV)
    {
      IF (dvDEV.SYSTEM = 0)             // if device is defined as local, i.e. system is 0
        RETURN "FORMAT('%d',dvDEV.NUMBER),':',FORMAT('%d',dvDEV.PORT),':',FORMAT('%d',SYSTEM_NUMBER)";
      ELSE 
    	RETURN "FORMAT('%d',dvDEV.NUMBER),':',FORMAT('%d',dvDEV.PORT),':',FORMAT('%d',dvDEV.SYSTEM)";
    }
    
    // DEFINE_FUNCTION DEVCHAN_TO_STRING
    // PARAMETER: 
    // dcDC - DEVCHAN USED
    // RETURNS:
    // DEVCHAN AS A STRING, IN BRACKETS
    DEFINE_FUNCTION CHAR[25] DEVCHAN_TO_STRING (DEVCHAN dcDC)
    {
      IF (dcDC.DEVICE.SYSTEM = 0)       // if device is defined as local, i.e. system is 0
      {
    	RETURN "'[',
    			FORMAT('%d',dcDC.DEVICE.NUMBER),':',
    			FORMAT('%d',dcDC.DEVICE.PORT),':',
    			FORMAT('%d',SYSTEM_NUMBER),
    			',',
    			FORMAT('%d',dcDC.CHANNEL),
    			']'";
      }
      ELSE
      {
    	RETURN "'[',
    			FORMAT('%d',dcDC.DEVICE.NUMBER),':',
    			FORMAT('%d',dcDC.DEVICE.PORT),':',
    			FORMAT('%d',dcDC.DEVICE.SYSTEM),
    			',',
    			FORMAT('%d',dcDC.CHANNEL),
    			']'";
      }
    }
    // DEFINE_FUNCTION DEV_CHAN_TO_STRING
    // PARAMETER: 
    // dvDEV - DEV USED
    // nCH   - CHAN USED
    // RETURNS:
    // DEVCHAN AS A STRING, IN BRACKETS
    DEFINE_FUNCTION CHAR[25] DEV_CHAN_TO_STRING (DEV dvDEV, INTEGER nCH)
    {
      IF (dvDEV.SYSTEM = 0)             // if device is defined as local, i.e. system is 0
      {
    	RETURN "'[',
    			FORMAT('%d',dvDEV.NUMBER),':',
    			FORMAT('%d',dvDEV.PORT),':',
    			FORMAT('%d',SYSTEM_NUMBER),
    			',',
    			FORMAT('%d',nCH),
    			']'";
      }
      ELSE
      {
      	RETURN "'[',
    			FORMAT('%d',dvDEV.NUMBER),':',
    			FORMAT('%d',dvDEV.PORT),':',
    			FORMAT('%d',dvDEV.SYSTEM),
    			',',
    			FORMAT('%d',nCH),
    			']'";
      }
    }
    
    // DEFINE_FUNCTION DEVLEV_TO_STRING
    // PARAMETER: 
    // dlDL - DEVLEV USED
    // RETURNS:
    // DEVLEV AS A STRING
    DEFINE_FUNCTION CHAR[25] DEVLEV_TO_STRING (DEVLEV dlDL)
    {
      IF (dlDL.DEVICE.SYSTEM = 0)       // if device is defined as local, i.e. system is 0
      {
    	RETURN "FORMAT('%d',dlDL.DEVICE.NUMBER),':',
    			FORMAT('%d',dlDL.DEVICE.PORT),':',
    			FORMAT('%d',SYSTEM_NUMBER),
    			',',
    			FORMAT('%d',dlDL.LEVEL)";
      }
      ELSE
      {
    	RETURN "FORMAT('%d',dlDL.DEVICE.NUMBER),':',
    			FORMAT('%d',dlDL.DEVICE.PORT),':',
    			FORMAT('%d',dlDL.DEVICE.SYSTEM),
    			',',
    			FORMAT('%d',dlDL.LEVEL)";
      }
    }
    // DEFINE_FUNCTION DEV_LEV_TO_STRING
    // PARAMETER: 
    // dvDEV - DEV USED
    // nLV   - LEV USED
    // RETURNS:
    // DEVLEV AS A STRING
    DEFINE_FUNCTION CHAR[25] DEV_LEV_TO_STRING (DEV dvDEV, INTEGER nLV)
    {
      IF (dvDEV.SYSTEM = 0)             // if device is defined as local, i.e. system is 0
      {
    	RETURN "FORMAT('%d',dvDEV.NUMBER),':',
    			FORMAT('%d',dvDEV.PORT),':',
    			FORMAT('%d',SYSTEM_NUMBER),
    			',',
    			FORMAT('%d',nLV)";
      }
      ELSE
      {
    	RETURN "FORMAT('%d',dvDEV.NUMBER),':',
    			FORMAT('%d',dvDEV.PORT),':',
    			FORMAT('%d',dvDEV.SYSTEM),
    			',',
    			FORMAT('%d',nLV)";
      }
    }
    
    // DEFINE_FUNCTION DPS_TO_STRING
    // PARAMETER: 
    // dvDEV - DEVICE USED
    // RETURNS:
    // dvDEV AS A STRING
    // this function differs from the original DEV_TO_STRING in that it always 
    // returns the actual system number, never system 0
    DEFINE_FUNCTION CHAR[17] DPS_TO_STRING (DEV dvDEV)
    {
      IF (dvDEV.SYSTEM = 0)             // if device is defined as local, i.e. system is 0
        RETURN "FORMAT('%d',dvDEV.NUMBER),':',FORMAT('%d',dvDEV.PORT),':',FORMAT('%d',SYSTEM_NUMBER)";
      ELSE 
    	RETURN "FORMAT('%d',dvDEV.NUMBER),':',FORMAT('%d',dvDEV.PORT),':',FORMAT('%d',dvDEV.SYSTEM)";
    }
    
    // DEFINE_CALL 'SEND 131 BYTE PACKETS TO MASTER'
    // BREAKS STRINGS UP INTO THE MAXIMUM SIZE 
    // THAT CAN BE SENT TO THE MASTER, SENDS
    // THEM TO THE MASTER.
    // PARAMETER:    
    // sTRING  - STRING TO BE SENT TO MASTER
    DEFINE_CALL 'SEND 131 BYTE PACKETS TO MASTER' (CHAR sSTRING[])
    STACK_VAR CHAR s131_BYTES[131];
    {
      WHILE (LENGTH_STRING(sSTRING) > 131)
      {
        s131_BYTES = LEFT_STRING(sSTRING,131);
        sSTRING = RIGHT_STRING(sSTRING,LENGTH_STRING(sSTRING)-131);
        SEND_STRING 0:0:0,"s131_BYTES";
      }
      IF (LENGTH_STRING(sSTRING))
      {
        SEND_STRING 0:0:0,"sSTRING";
      }
    }
    
    // CALL 'SEND 7BIT ASCII TO DEBUG'
    // PASSES ASCII CHARACTERS UNFORMATTED, ASCII STRINGS INSIDE SINGLE-QUOTES
    // FORMATS CHARS >= $7F (del) AS 2 DIGIT HEX, SEPERATED BY COMMAS 
    // FORMATS CONTROL CHARACTERS AS 2 DIGIT HEX, SEPERATED BY COMMAS
    // ASCII STRINGS SEPERATED FROM HEX BY COMMAS
    // PARAMETERS: 
    // dvDEBUG IS DESTINATION
    // STR1 IS HEADER 
    // STR2 IS DATA TO BE FORMATTED
    // nLine IS LINE LENGTH. 0 = default = 80 for nMode 2, 67 for all others.
    // nMode is MSG ON mode. 2 = append <cr>,<lf> to lines.
    DEFINE_CALL 'SEND 7BIT ASCII TO DEBUG' (DEV dvDEBUG,CHAR STR1[],CHAR STR2[],INTEGER nLINE,INTEGER nMODE)
    STACK_VAR integer X; integer STR1_LEN; integer STR2_LEN; integer ASCII_PACKET_LEN;
    STACK_VAR char ASCII[16000];
    STACK_VAR INTEGER FIRST_STRING_SENT;
    {
      STR1_LEN = LENGTH_ARRAY(STR1);
      STR2_LEN = LENGTH_ARRAY(STR2);
      FOR (X = 1; X <= STR2_LEN; X++)
      {
                                        // IF IT'S A CONTROL CHARACTER 
    									// OR DEL OR EXTENDED ASCII
        IF (STR2[X] < $20 || STR2[X] >= $7F)
        {
          IF (X = STR2_LEN)             // IF IT'S THE LAST BYTE
          {
                                        // JUST PRINT $XX
            ASCII = "ASCII,FORMAT('$%0 2X',STR2[X])";
          }
    									// IF THE NEXT BYTE IS A CONTROL CHARACTER 
    									// OR DEL OR EXTENDED ASCII
          ELSE IF (STR2[X+1] < $20 || STR2[X+1] > $7F)
          {
                                        // END WITH COMMA
            ASCII = "ASCII,FORMAT('$%0 2X,',STR2[X])";
          }
          ELSE
          {
                                        // END WITH COMMA/SINGLE QUOTE
            ASCII = "ASCII,FORMAT('$%0 2X,''',STR2[X])";
          }
        }
        ELSE                            // IF IT'S PRINTABLE
        {
          SELECT
          {
            ACTIVE (X = 1):             // IF IT'S THE FIRST BYTE
            {
              IF (X = STR2_LEN ||       // IF IT'S THE ONLY BYTE OR
                  STR2[X+1] < $20 ||    // THE NEXT BYTE IS A CONTROL CHARACTER OR
                  STR2[X+1] >= $7F)     // THE NEXT BYTE IS DEL OR EXTENDED ASCII
              {
                                        // PUT IT IN SINGLE QUOTES
                ASCII = "'''',STR2[X],''''";
              }
              ELSE
              {
                ASCII = "'''',STR2[X]";  // LEADING SINGLE QUOTE ONLY
              }
            }
            ACTIVE (X = STR2_LEN):      // IF IT'S THE LAST BYTE
            {
                                        // TRAILING SINGLE QUOTE ONLY
              ASCII = "ASCII,STR2[X],''''";
            }
            ACTIVE (STR2[X+1] < $20):   // IF THE NEXT BYTE IS A CONTROL CHARACTER
            {
                                        // TRAILING SINGLE QUOTE/COMMA
              ASCII = "ASCII,STR2[X],''','";
            }
            ACTIVE (STR2[X+1] >= $7F):  // IF THE NEXT BYTE IS DEL OR EXTENDED ASCII
            {
                                        // TRAILING SINGLE QUOTE/COMMA
              ASCII = "ASCII,STR2[X],''','";
            }
            ACTIVE (1):
            {
              ASCII = "ASCII,STR2[X]";  // JUST PRINT THE CHARACTER
            }
          }
        }
      }
       
      SELECT                            // SET THE ASCII PACKET LENGTH
      {
        ACTIVE (nLINE > 131):           // MAX IS 131 CHARACTER LINE
        {
          ASCII_PACKET_LEN = 131 - STR1_LEN;
        }
        ACTIVE (nLINE > STR1_LEN && nLINE <= 131):    
        {
          ASCII_PACKET_LEN = nLINE - STR1_LEN;
        }
        ACTIVE (nMODE = 2):             // MODE 2 DEFAULT TO 80 CHARACTER LINE
        {
          ASCII_PACKET_LEN = 80 - STR1_LEN;
        }
        ACTIVE (1):                     // DEFAULT TO 67 CHARACTER LINE
        {
          ASCII_PACKET_LEN = 67 - STR1_LEN;
        }
      }
                                        // SEND THE DATA
                                        // WHILE THERE'S MORE THAN ONE LINE ...
      WHILE (LENGTH_ARRAY(ASCII) > ASCII_PACKET_LEN)
      {
        IF (nMODE = 2)
        {
          SEND_STRING dvDEBUG,"STR1,LEFT_STRING(ASCII,ASCII_PACKET_LEN),13,10";
        }
        ELSE
        {
          SEND_STRING dvDEBUG,"STR1,LEFT_STRING(ASCII,ASCII_PACKET_LEN)";
        }
        ASCII = RIGHT_STRING(ASCII,LENGTH_STRING(ASCII)-ASCII_PACKET_LEN)
    	
    	IF (!FIRST_STRING_SENT)			// replace STR1 with spaces after first pass
    	{
    	  ON[FIRST_STRING_SENT]
    	  STR1 = LEFT_STRING(__SPACES__,LENGTH_STRING(STR1))
    	}
      } 
    
      IF (LENGTH_ARRAY(ASCII))          // IF THERE'S ANYTHING LEFT SEND IT
      {  
        IF (nMODE = 2)
        {
          SEND_STRING dvDEBUG,"STR1,ASCII,13,10";
        }
        ELSE
        {
          SEND_STRING dvDEBUG,"STR1,ASCII";
        }
      }
    }
    
    // CALL 'SEND ASCII TO DEBUG'
    // PASSES ASCII CHARACTERS UNFORMATTED, ASCII STRINGS INSIDE SINGLE-QUOTES
    // FORMATS CONTROL CHARACTERS AS 2 DIGIT HEX, SEPERATED BY COMMAS
    // ASCII STRINGS SEPERATED FROM HEX BY COMMAS
    // PARAMETERS: 
    // dvDEBUG IS DESTINATION
    // STR1 IS HEADER 
    // STR2 IS DATA TO BE FORMATTED
    // nLine IS LINE LENGTH. 0 = default = 80 for nMode 2, 67 for all others.
    // nMode is MSG ON mode. 2 = append <cr>,<lf> to lines.
    DEFINE_CALL 'SEND ASCII TO DEBUG' (DEV dvDEBUG,CHAR STR1[],CHAR STR2[],INTEGER nLINE,INTEGER nMODE)
    STACK_VAR integer X; integer STR1_LEN; integer STR2_LEN; integer ASCII_PACKET_LEN;
    STACK_VAR char ASCII[16000];
    STACK_VAR INTEGER FIRST_STRING_SENT;
    {
      STR1_LEN = LENGTH_ARRAY(STR1);
      STR2_LEN = LENGTH_ARRAY(STR2);
      FOR (X = 1; X <= STR2_LEN; X++)
      {
    									// IF IT'S A CONTROL CHARACTER
        IF (STR2[X] < $20 || STR2[X] = $7F)
        {
          IF (X = STR2_LEN)             // IF IT'S THE LAST BYTE
          {
                                        // JUST PRINT $XX
            ASCII = "ASCII,FORMAT('$%0 2X',STR2[X])";
          }
    									// IF THE NEXT BYTE IS A CONTROL CHARACTER
          ELSE IF (STR2[X+1] < $20 || STR2[X+1] = $7F)
          {
                                        // END WITH COMMA
            ASCII = "ASCII,FORMAT('$%0 2X,',STR2[X])";
          }
          ELSE
          {
                                        // END WITH COMMA/SINGLE QUOTE
            ASCII = "ASCII,FORMAT('$%0 2X,''',STR2[X])";
          }
        }
        ELSE                            // IF IT'S PRINTABLE
        {
          SELECT
          {
            ACTIVE (X = 1):             // IF IT'S THE FIRST BYTE
            {
              IF (X = STR2_LEN ||       // IF IT'S THE ONLY BYTE OR
    									// THE NEXT BYTE IS A CONTROL CHARACTER
                  STR2[X+1] < $20 || STR2[X+1] = $7F)
              {
                                        // PUT IT IN SINGLE QUOTES
                ASCII = "'''',STR2[X],''''";
              }
              ELSE
              {
                ASCII = "'''',STR2[X]";  // LEADING SINGLE QUOTE ONLY
              }
            }
            ACTIVE (X = STR2_LEN):      // IF IT'S THE LAST BYTE
            {
                                        // TRAILING SINGLE QUOTE ONLY
              ASCII = "ASCII,STR2[X],''''";
            }
    									// IF THE NEXT BYTE IS A CONTROL CHARACTER
            ACTIVE (STR2[X+1] < $20 || STR2[X+1] = $7F):
            {
                                        // TRAILING SINGLE QUOTE/COMMA
              ASCII = "ASCII,STR2[X],''','";
            }
            ACTIVE (1):
            {
              ASCII = "ASCII,STR2[X]";  // JUST PRINT THE CHARACTER
            }
          }
        }
      }
    
      SELECT                            // SET THE ASCII PACKET LENGTH
      {
        ACTIVE (nLINE > 131):           // MAX IS 131 CHARACTER LINE
        {
          ASCII_PACKET_LEN = 131 - STR1_LEN;
        }
        ACTIVE (nLINE > STR1_LEN && nLINE <= 131):    
        {
          ASCII_PACKET_LEN = nLINE - STR1_LEN;
        }
        ACTIVE (nMODE = 2):             // MODE 2 DEFAULT TO 80 CHARACTER LINE
        {
          ASCII_PACKET_LEN = 80 - STR1_LEN;
        }
        ACTIVE (1):                     // DEFAULT TO 67 CHARACTER LINE
        {
          ASCII_PACKET_LEN = 67 - STR1_LEN;
        }
      }
                                        // SEND THE DATA
                                        // WHILE THERE'S MORE THAN ONE LINE ...
      WHILE (LENGTH_ARRAY(ASCII) > ASCII_PACKET_LEN)
      {
        IF (nMODE = 2)
        {
          SEND_STRING dvDEBUG,"STR1,LEFT_STRING(ASCII,ASCII_PACKET_LEN),13,10";
        }
        ELSE
        {
          SEND_STRING dvDEBUG,"STR1,LEFT_STRING(ASCII,ASCII_PACKET_LEN)";
        }
        ASCII = RIGHT_STRING(ASCII,LENGTH_STRING(ASCII)-ASCII_PACKET_LEN)
    	
    	IF (!FIRST_STRING_SENT)			// replace STR1 with spaces after first pass
    	{
    	  ON[FIRST_STRING_SENT]
    	  STR1 = LEFT_STRING(__SPACES__,LENGTH_STRING(STR1))
    	}
      } 
    
      IF (LENGTH_ARRAY(ASCII))          // IF THERE'S ANYTHING LEFT SEND IT
      {  
        IF (nMODE = 2)
        {
          SEND_STRING dvDEBUG,"STR1,ASCII,13,10";
        }
        ELSE
        {
          SEND_STRING dvDEBUG,"STR1,ASCII";
        }
      }
    }
    
    // CALL 'SEND ASCII TO MASTER'
    // PASSES ASCII CHARACTERS UNFORMATTED, ASCII STRINGS INSIDE SINGLE-QUOTES
    // FORMATS CONTROL CHARACTERS AS 2 DIGIT HEX, SEPERATED BY COMMAS
    // ASCII STRINGS SEPERATED FROM HEX BY COMMAS
    // PARAMETERS: 
    // STR1 IS HEADER 
    // STR2 IS DATA TO BE FORMATTED
    DEFINE_CALL 'SEND ASCII TO MASTER' (STR1[],STR2[])
    STACK_VAR integer X; integer STR1_LEN; integer STR2_LEN; integer ASCII_PACKET_LEN;
    STACK_VAR char ASCII[16000];
    STACK_VAR INTEGER FIRST_STRING_SENT;
    {
      STR1_LEN = LENGTH_ARRAY(STR1);
      STR2_LEN = LENGTH_ARRAY(STR2);
      FOR (X = 1; X <= STR2_LEN; X++)
      {
    									// IF IT'S A CONTROL CHARACTER
        IF (STR2[X] < $20 || STR2[X] = $7F)
        {
          IF (X = STR2_LEN)             // IF IT'S THE LAST BYTE
          {
                                        // JUST PRINT $XX
            ASCII = "ASCII,FORMAT('$%0 2X',STR2[X])";
          }
    									// IF THE NEXT BYTE IS A CONTROL CHARACTER
          ELSE IF (STR2[X+1] < $20 || STR2[X+1] = $7F)
          {
                                        // END WITH COMMA
            ASCII = "ASCII,FORMAT('$%0 2X,',STR2[X])";
          }
          ELSE
          {
                                        // END WITH COMMA/SINGLE QUOTE
            ASCII = "ASCII,FORMAT('$%0 2X,''',STR2[X])";
          }
        }
        ELSE                            // IF IT'S PRINTABLE
        {
          SELECT
          {
            ACTIVE (X = 1):             // IF IT'S THE FIRST BYTE
            {
              IF (X = STR2_LEN ||       // IF IT'S THE ONLY BYTE OR
    									// THE NEXT BYTE IS A CONTROL CHARACTER
                  STR2[X+1] < $20 || STR2[X+1] = $7F)
              {
                                        // PUT IT IN SINGLE QUOTES
                ASCII = "'''',STR2[X],''''";
              }
              ELSE
              {
                ASCII = "'''',STR2[X]";  // LEADING SINGLE QUOTE ONLY
              }
            }
            ACTIVE (X = STR2_LEN):      // IF IT'S THE LAST BYTE
            {
                                        // TRAILING SINGLE QUOTE ONLY
              ASCII = "ASCII,STR2[X],''''";
            }
    									// IF THE NEXT BYTE IS A CONTROL CHARACTER
            ACTIVE (STR2[X+1] < $20 || STR2[X+1] = $7F):
            {
                                        // TRAILING SINGLE QUOTE/COMMA
              ASCII = "ASCII,STR2[X],''','";
            }
            ACTIVE (1):
            {
              ASCII = "ASCII,STR2[X]";  // JUST PRINT THE CHARACTER
            }
          }
        }
      }
    
      ASCII_PACKET_LEN = 67 - STR1_LEN; // 80 CHARACTER LINE
                                        // 67 IS THE STRING LENGTH (MAX IS 131)
                                        // 13 CHARACTERS FOR TIMESTAMP
      WHILE (LENGTH_ARRAY(ASCII) > ASCII_PACKET_LEN)
      {
        SEND_STRING 0:0:0,"STR1,LEFT_STRING(ASCII,ASCII_PACKET_LEN)";
        ASCII = RIGHT_STRING(ASCII,LENGTH_STRING(ASCII)-ASCII_PACKET_LEN);
    	
    	IF (!FIRST_STRING_SENT)			// replace STR1 with spaces after first pass
    	{
    	  ON[FIRST_STRING_SENT]
    	  STR1 = LEFT_STRING(__SPACES__,LENGTH_STRING(STR1))
    	}
      }  
      IF (LENGTH_ARRAY(ASCII))
      {
        SEND_STRING 0:0:0,"STR1,ASCII";
      }
    }
    
    // 'SEND DECIMAL TO DEBUG'
    // FORMATS ALL CHARACTERS AS 3 DIGIT DECIMAL, SEPERATED BY COMMAS
    // PARAMETERS: 
    // dvDEBUG IS DESTINATION
    // STR1 IS HEADER
    // STR2 IS DATA TO BE FORMATTED
    // nLine IS LINE LENGTH. 0 = default = 80 for nMode 2, 67 for all others.
    // nMode is MSG ON mode. 2 = append <cr>,<lf> to lines.
    DEFINE_CALL 'SEND DECIMAL TO DEBUG' (DEV dvDEBUG,CHAR STR1[],CHAR STR2[],INTEGER nLine,INTEGER nMode)
    STACK_VAR integer X; integer STR1_LEN; integer STR2_LEN; integer ASCII_PACKET_LEN;
    STACK_VAR char ASCII[16000];
    STACK_VAR INTEGER FIRST_STRING_SENT;
    {
      STR1_LEN = LENGTH_ARRAY(STR1);
      STR2_LEN = LENGTH_ARRAY(STR2);
    
      FOR (X = 1; X <= STR2_LEN; X++)   // BUILD UP ASCII STRING FROM STR2
      {
        IF (X = STR2_LEN)               // IF IT'S THE LAST BYTE
        {
          ASCII = "ASCII,FORMAT('%03d',STR2[X])";
        }
        ELSE
        {
          ASCII = "ASCII,FORMAT('%03d,',STR2[X])";
        }
      }
      
      SELECT                            // SET THE ASCII PACKET LENGTH
      {
        ACTIVE (nLINE > 131):           // MAX IS 131 CHARACTER LINE
        {
          ASCII_PACKET_LEN = 131 - STR1_LEN;
        }
        ACTIVE (nLINE > STR1_LEN && nLINE <= 131):    
        {
          ASCII_PACKET_LEN = nLINE - STR1_LEN;
        }
        ACTIVE (nMODE = 2):             // MODE 2 DEFAULT TO 80 CHARACTER LINE
        {
          ASCII_PACKET_LEN = 80 - STR1_LEN;
        }
        ACTIVE (1):                     // DEFAULT TO 67 CHARACTER LINE
        {
          ASCII_PACKET_LEN = 67 - STR1_LEN;
        }
      }
                                        // SEND DATA
                                        // WHILE THERE'S MORE THAN ONE LINE...
      WHILE (LENGTH_ARRAY(ASCII) > ASCII_PACKET_LEN)
      {
        IF (nMODE = 2)
        {
          SEND_STRING dvDEBUG,"STR1,LEFT_STRING(ASCII,ASCII_PACKET_LEN),13,10";
        }
        ELSE
        {
          SEND_STRING dvDEBUG,"STR1,LEFT_STRING(ASCII,ASCII_PACKET_LEN)";
        }
        ASCII = RIGHT_STRING(ASCII,LENGTH_STRING(ASCII)-ASCII_PACKET_LEN);
    	
    	IF (!FIRST_STRING_SENT)			// replace STR1 with spaces after first pass
    	{
    	  ON[FIRST_STRING_SENT]
    	  STR1 = LEFT_STRING(__SPACES__,LENGTH_STRING(STR1))
    	}
      } 
    
      IF (LENGTH_ARRAY(ASCII))          // IF THERE'S ANYTHING LEFT SEND IT
      {  
        IF (nMODE = 2)
        {
          SEND_STRING dvDEBUG,"STR1,ASCII,13,10";
        }
        ELSE
        {
          SEND_STRING dvDEBUG,"STR1,ASCII";
        }
      }
    }
    
    /* CALL 'SEND DEVICE_INFO TO DEBUG'                        */
    /* FUNCTION:   Get device info structure for a device,     */
    /*             then send the info to a debug device such   */ 
    /*             as the master's debug port.                 */
    /* PARAMETERS: dvDEBUG   - device to receive device info   */
    /*             dvDEV     - device from which to get info   */ 
    DEFINE_CALL 'SEND DEVICE_INFO TO DEBUG' (DEV dvDEBUG, DEV dvDEV)
    STACK_VAR DEV_INFO_STRUCT devinfo 
    STACK_VAR CHAR sSTR[100]
    {
      IF (DEVICE_ID(dvDEV))             // if device is online
      {
    	DEVICE_INFO(dvDEV,devinfo)
      
    	send_string dvDebug,"'D:P:S ',DPS_TO_STRING(dvDEV)"
    
    	if (length_array(devinfo.MANUFACTURER_STRING))
    	  send_string dvDebug,"'Manufacturer ',devinfo.MANUFACTURER_STRING"
    	else
    	  send_string dvDebug,"'Manufacturer not available'"
    
    	if (devinfo.MANUFACTURER)
    	  send_string dvDebug,"'Manufacturer ID ',ITOA(devinfo.MANUFACTURER)"
    	else	
    	  send_string dvDebug,"'Manufacturer ID not available'"
    
    	if (length_array(devinfo.DEVICE_ID_STRING))	
    	  send_string dvDebug,"'Device ',devinfo.DEVICE_ID_STRING"
    	else
    	  send_string dvDebug,"'Device not available'"
    
    	send_string dvDebug,"'Device ID $',ITOHEX(devinfo.DEVICE_ID)"
    
    	if (length_array(devinfo.VERSION))
    	  send_string dvDebug,"'Version ',devinfo.VERSION"
    	else
    	  send_string dvDebug,"'Version not available'"
    
    	if (devinfo.FIRMWARE_ID)
    	  send_string dvDebug,"'Firmware ID $',ITOHEX(devinfo.FIRMWARE_ID)"
    	else 
    	  send_string dvDebug,"'Firmware ID not available'"
    
    	if (length_array(devinfo.SERIAL_NUMBER))
    	{
    	                                // if serial_number is blank for Netlinx device,
    									// first byte is $00
    	  if (find_string(devinfo.SERIAL_NUMBER,"$00",1) = 1)
    									// 16 0's
    	    send_string dvDebug,"'Serial Number 0000000000000000'"
    
    									// trim excess bytes if SN is not 16 chars long
    	  else if (find_string(devinfo.SERIAL_NUMBER,"$00",1) > 1)
    		send_string dvDebug,"'Serial Number ',
    											LEFT_STRING(devinfo.SERIAL_NUMBER,
    LENGTH_ARRAY(devinfo.SERIAL_NUMBER) - (17 - FIND_STRING(devinfo.serial_number,"$00",1))
    													   )"
    
    	  else                          // if no $00, just send the whole string
    	    send_string dvDebug,"'Serial Number ',devinfo.SERIAL_NUMBER"
    	}
    	else                            // this should never happen
    	  send_string dvDebug,"'Serial Number not available'"
    
    	SWITCH (devinfo.SOURCE_TYPE)
    	{
    	  CASE SOURCE_TYPE_NO_ADDRESS:
    		send_string dvDebug,"'Source Type $00: not available'"
    	  CASE SOURCE_TYPE_NEURON_ID:
    		send_string dvDebug,"'Source Type $01: connected via ICSNet'"
    	  CASE SOURCE_TYPE_IP_ADDRESS:
    		send_string dvDebug,"'Source Type $02: connected via ethernet'"
    	  CASE SOURCE_TYPE_AXLINK:
    		send_string dvDebug,"'Source Type $03: connected via AXLink'"
    	  CASE SOURCE_TYPE_NEURON_SUBNODE_ICSP:
    		send_string dvDebug,"'Source Type $10: connected via ICSNet'"
    	  CASE SOURCE_TYPE_NEURON_SUBNODE_PL:
    		send_string dvDebug,"'Source Type $11: connected via ICSNet'"
    	  CASE SOURCE_TYPE_IP_SOCKET_ADDRESS:
    		send_string dvDebug,"'Source Type $12: connected via ethernet'"
    	  CASE SOURCE_TYPE_RS232:
    		send_string dvDebug,"'Source Type $13: connected via RS232'"
    	  CASE $20:
    		send_string dvDebug,"'Source Type $20: internal to the NetLinx controller'"
    	  DEFAULT: 
    		send_string dvDebug,FORMAT('Source Type $%02X: unknown',devinfo.SOURCE_TYPE)
    	}
    
    	if (length_array(devinfo.SOURCE_STRING))
    	  send_string dvDebug,"'Source String ',devinfo.SOURCE_STRING"
    	else 
    	  send_string dvDebug,"'Source String not available'"
      }
      else
    	send_string dvDebug,"'D:P:S ',DPS_TO_STRING(dvDEV),' not online'"
    }
    
    // 'SEND INTEGER TO DEBUG'
    // DOES NOT FORMAT CHARACTERS, FORMATS LINE LENGTH ONLY
    // PARAMETERS: 
    // dvDEBUG IS DESTINATION
    // STR1 IS HEADER
    // STR2 IS DATA TO BE FORMATTED
    // nLine IS LINE LENGTH. 0 = default = 80 for nMode 2, 67 for all others.
    // nMode is MSG ON mode. 2 = append <cr>,<lf> to lines.
    DEFINE_CALL 'SEND INTEGER TO DEBUG' (DEV dvDEBUG,CHAR STR1[],CHAR STR2[],INTEGER nLine,INTEGER nMode)
    STACK_VAR integer STR1_LEN; integer STR2_LEN; integer PACKET_LEN;
    STACK_VAR char sTEMP[16000]; 
    STACK_VAR INTEGER FIRST_STRING_SENT;
    {
      STR1_LEN = LENGTH_ARRAY(STR1);
      STR2_LEN = LENGTH_ARRAY(STR2);
    
      sTEMP = STR2;                     // BUILD UP TEMP STRING FROM STR2
      
      SELECT                            // SET THE PACKET LENGTH
      {
        ACTIVE (nLINE > 131):           // MAX IS 131 CHARACTER LINE
        {
          PACKET_LEN = 131 - STR1_LEN;
        }
        ACTIVE (nLINE > STR1_LEN && nLINE <= 131):    
        {
          PACKET_LEN = nLINE - STR1_LEN;
        }
        ACTIVE (nMODE = 2):             // MODE 2 DEFAULT TO 80 CHARACTER LINE
        {
          PACKET_LEN = 80 - STR1_LEN;
        }
        ACTIVE (1):                     // DEFAULT TO 67 CHARACTER LINE
        {
          PACKET_LEN = 67 - STR1_LEN;
        }
      }
                                        // SEND DATA
                                        // WHILE THERE'S MORE THAN ONE LINE...
      WHILE (LENGTH_ARRAY(sTEMP) > PACKET_LEN)
      {
        IF (nMODE = 2)
        {
          SEND_STRING dvDEBUG,"STR1,LEFT_STRING(sTEMP,PACKET_LEN),13,10";
        }
        ELSE
        {
          SEND_STRING dvDEBUG,"STR1,LEFT_STRING(sTEMP,PACKET_LEN)";
        }
        sTEMP = RIGHT_STRING(sTEMP,LENGTH_STRING(sTEMP)-PACKET_LEN);
    	
    	IF (!FIRST_STRING_SENT)			// replace STR1 with spaces after first pass
    	{
    	  ON[FIRST_STRING_SENT]
    	  STR1 = LEFT_STRING(__SPACES__,LENGTH_STRING(STR1))
    	}
      } 
    
      IF (LENGTH_ARRAY(sTEMP))          // IF THERE'S ANYTHING LEFT SEND IT
      {  
        IF (nMODE = 2)
        {
          SEND_STRING dvDEBUG,"STR1,sTEMP,13,10";
        }
        ELSE
        {
          SEND_STRING dvDEBUG,"STR1,sTEMP";
        }
      }
    }
    
    // 'SEND ITOHEX TO DEBUG'
    // FORMATS ALL CHARACTERS AS 2 DIGIT HEX, SEPERATED BY COMMAS
    // PARAMETERS: 
    // dvDEBUG IS DESTINATION
    // STR1 IS HEADER
    // STR2 IS DATA TO BE FORMATTED
    // nLine IS LINE LENGTH. 0 = default = 80 for nMode 2, 67 for all others.
    // nMode is MSG ON mode. 2 = append <cr>,<lf> to lines.
    DEFINE_CALL 'SEND ITOHEX TO DEBUG' (DEV dvDEBUG,CHAR STR1[],CHAR STR2[],INTEGER nLine,INTEGER nMode)
    STACK_VAR integer X; integer STR1_LEN; integer STR2_LEN; integer  ASCII_PACKET_LEN;
    STACK_VAR char ASCII[16000];
    STACK_VAR INTEGER FIRST_STRING_SENT;
    {
      STR1_LEN = LENGTH_ARRAY(STR1);
      STR2_LEN = LENGTH_ARRAY(STR2);
    
      FOR (X = 1; X <= STR2_LEN; X++)   // BUILD UP ASCII STRING FROM STR2
      {
        IF (X = STR2_LEN)               // IF IT'S THE LAST BYTE
        {
          ASCII = "ASCII,FORMAT('$%0 2X',STR2[X])";
        }
        ELSE
        {
          ASCII = "ASCII,FORMAT('$%0 2X,',STR2[X])";
        }
      }
      
      SELECT                            // SET THE ASCII PACKET LENGTH
      {
        ACTIVE (nLINE > 131):           // MAX IS 131 CHARACTER LINE
        {
          ASCII_PACKET_LEN = 131 - STR1_LEN;
        }
        ACTIVE (nLINE > STR1_LEN && nLINE <= 131):    
        {
          ASCII_PACKET_LEN = nLINE - STR1_LEN;
        }
        ACTIVE (nMODE = 2):             // MODE 2 DEFAULT TO 80 CHARACTER LINE
        {
          ASCII_PACKET_LEN = 80 - STR1_LEN;
        }
        ACTIVE (1):                     // DEFAULT TO 67 CHARACTER LINE
        {
          ASCII_PACKET_LEN = 67 - STR1_LEN;
        }
      }
                                        // SEND DATA
                                        // WHILE THERE'S MORE THAN ONE LINE...
      WHILE (LENGTH_ARRAY(ASCII) > ASCII_PACKET_LEN)
      {
        IF (nMODE = 2)
        {
          SEND_STRING dvDEBUG,"STR1,LEFT_STRING(ASCII,ASCII_PACKET_LEN),13,10";
        }
        ELSE
        {
          SEND_STRING dvDEBUG,"STR1,LEFT_STRING(ASCII,ASCII_PACKET_LEN)";
        }
        ASCII = RIGHT_STRING(ASCII,LENGTH_STRING(ASCII)-ASCII_PACKET_LEN);
    	
    	IF (!FIRST_STRING_SENT)			// replace STR1 with spaces after first pass
    	{
    	  ON[FIRST_STRING_SENT]
    	  STR1 = LEFT_STRING(__SPACES__,LENGTH_STRING(STR1))
    	}
      } 
    
      IF (LENGTH_ARRAY(ASCII))          // IF THERE'S ANYTHING LEFT SEND IT
      {  
        IF (nMODE = 2)
        {
          SEND_STRING dvDEBUG,"STR1,ASCII,13,10";
        }
        ELSE
        {
          SEND_STRING dvDEBUG,"STR1,ASCII";
        }
      }
    }
    
    // SEND_ITOHEX_TO_MASTER
    // FORMATS ALL CHARACTERS AS 2 DIGIT HEX, SEPERATED BY COMMAS
    // PARAMETERS: STR1 IS HEADER; STR2 IS DATA TO BE FORMATTED;
    DEFINE_CALL 'SEND ITOHEX TO MASTER' (STR1[],STR2[])
    STACK_VAR integer X; integer STR1_LEN; integer STR2_LEN; integer ASCII_PACKET_LEN;
    STACK_VAR char ASCII[16000];
    STACK_VAR INTEGER FIRST_STRING_SENT;
    {
      STR1_LEN = LENGTH_ARRAY(STR1);
      STR2_LEN = LENGTH_ARRAY(STR2);
      FOR (X = 1; X <= STR2_LEN; X++)
      {
        IF (X = STR2_LEN)               // IF IT'S THE LAST BYTE
        {
          ASCII = "ASCII,FORMAT('$%0 2X',STR2[X])";
        }
        ELSE
        {
          ASCII = "ASCII,FORMAT('$%0 2X,',STR2[X])";
        }
      }
       
      ASCII_PACKET_LEN = 67 - STR1_LEN; // 80 CHARACTER LINE
                                        // 67 IS THE STRING LENGTH (MAX IS 131)
                                        // 13 CHARACTERS FOR TIMESTAMP
      WHILE (LENGTH_ARRAY(ASCII) > ASCII_PACKET_LEN)
      {
        SEND_STRING 0:0:0,"STR1,LEFT_STRING(ASCII,ASCII_PACKET_LEN)";
        ASCII = RIGHT_STRING(ASCII,LENGTH_STRING(ASCII)-ASCII_PACKET_LEN);
    	
    	IF (!FIRST_STRING_SENT)			// replace STR1 with spaces after first pass
    	{
    	  ON[FIRST_STRING_SENT]
    	  STR1 = LEFT_STRING(__SPACES__,LENGTH_STRING(STR1))
    	}
      }  
      IF (LENGTH_ARRAY(ASCII))
      {  
        SEND_STRING 0:0:0,"STR1,ASCII";
      }
    }
    
    /* CALL 'STRING TO DEV'                                    */
    /* FUNCTION: Takes ASCII string of the form '...<dev>' or  */
    /*           '...<dev>:<prt>:<sys>' and puts those values  */
    /*           into dvDEV.                                   */
    /* PARAMETERS: Txt   - String that contains the dv:prt:sys */
    /*                     as ASCII text.                      */
    /*             dvDEV - storage for the returned value      */
    DEFINE_CALL 'STRING TO DEV' (char Txt[],dev dvDEV)
    STACK_VAR INTEGER DV
    STACK_VAR INTEGER PRT
    STACK_VAR INTEGER SYS
    STACK_VAR INTEGER WherePrt
    STACK_VAR INTEGER WhereSys
    {
    									/*********************/
                                        /* get device number */
    									/*********************/
      DV = ATOI(Txt)                    // if Txt does not contain a number,
    		                            // DV will be 0 (the master)
    
    									/*******************/
                                        /* get port number */
    									/*******************/
      IF (FIND_STRING(Txt,':',2))       // if Txt is of form '...<dv>:<prt>...'
      {
        WherePrt = FIND_STRING(Txt,':',1)
        IF (WherePrt)                   // if there might be a port number
        {
    									// if port 0 was entered and 
    									// Txt if of form '...<dv>:<prt>:<sys>'
    	  IF (FIND_STRING(Txt,':0:',1) = WherePrt)
    	    PRT = 0 
          ELSE
          {
    	    PRT = ATOI(RIGHT_STRING(Txt,LENGTH_ARRAY(Txt)-WherePrt))
    	    IF (PRT = 0)                // if Txt does not contain a number past the 
    		  PRT = 1                   // first ':', PRT will be 1
    	  }
        }
      }
      ELSE								// if Txt does not contain a number past the 
        PRT = 1                         // first ':', PRT will be 1
    
    									/*********************/
                                        /* get system number */
    									/*********************/
    									// if Txt is of form '...<dv>:<prt>:<sys>'
    									// note: SYS 0 means local system
      IF (FIND_STRING(Txt,':',WherePrt + 1))
      {
    	WhereSys = FIND_STRING(Txt,':',WherePrt + 1)
    	SYS = ATOI(RIGHT_STRING(Txt,LENGTH_ARRAY(Txt)-WhereSys))
      }
      dvDEV = DV:PRT:SYS               
    }
    
    (***********************************************************)
    (*                THE EVENTS GOES BELOW                    *)
    (***********************************************************)
    DEFINE_EVENT
    
    DATA_EVENT[0:1:0]
    {
      ONLINE:
      {
        wait 50                         // WAIT FOR DEVICE HOLDOFF
        {
          // WHAT VERSION? 
          SEND_STRING 0:0:0,"'Using lib ',__DEBUG_LIB_NAME__,
                                    ', v',__DEBUG_LIB_VERSION__";
        }
      }
    }
    
    #END_IF
    (***********************************************************)
    (*                     END OF PROGRAM                      *)
    (*        DO NOT PUT ANY CODE BELOW THIS COMMENT           *)
    (***********************************************************)
    
    
Sign In or Register to comment.