Home AMX User Forum NetLinx Studio

BCD madness (Getting frustrated)

Be warned, I'm knocking about 5 years of rust off of my ACE certification with an automated theater project. The DVD player is a Sony 400-Disc Blue-Ray changer (7000ES), and I'm connected VIA RS-232. The DVD player returns status strings prompted by polling from the module. The strings give the status of the movie playing, and I'm trying to use them to detect the position of a movie to automate theater start-up and shutdown. (A royal PITA)

The issue I'm having is that the status is received as binary coded decimal. I've read a few threads here on how to parse and translate these strings into actual integers, but have so far been unsuccessful.

The string consists of the header, 2 Disc number bytes, 2 title number bytes, 2 chapter number bytes, and a transport status byte. Anything after that I really don't care about, and erase the rest of the string.
It looks like this, where:
$88,$82 = Disc Data to follow
$01,$39 = Disc Number (Disc 139)
$00,$04 = Title number (Title #4)
$00,$01 = Chapter number (Chapter 4)
$11 = Transport status ($11 = Play)
String From [41002:1:1]-[$02$0A$88$82$01$39$00$04$00$04$11$0C$C8]
The DATA_EVENT looks like this:
REMOVE_STRING(vdvDVD_Buffer,"$88,$82",1)
	    cDiscNo1 = LEFT_STRING(vdvDVD_Buffer,1)
	    REMOVE_STRING(vdvDVD_Buffer,cDiscNo1,1)
	    cDiscNo2 = LEFT_STRING(vdvDVD_Buffer,1)
	    REMOVE_STRING(vdvDVD_Buffer,cDiscNo2,1)
	    cTitleNo1 = LEFT_STRING(vdvDVD_Buffer,1)
	    REMOVE_STRING(vdvDVD_Buffer,cTitleNo1,1)
	    cTitleNo2 = LEFT_STRING(vdvDVD_Buffer,1)
	    REMOVE_STRING(vdvDVD_Buffer,cTitleNo2,1)
	    cChapterNo1 = LEFT_STRING(vdvDVD_Buffer,1)
	    REMOVE_STRING(vdvDVD_Buffer,cChapterNo1,1)
	    cChapterNo2 = LEFT_STRING(vdvDVD_Buffer,1)
	    REMOVE_STRING(vdvDVD_Buffer,cChapterNo2,1)
	    DVD_Status_TransportStatus = LEFT_STRING(vdvDVD_Buffer,1)
	    REMOVE_STRING(vdvDVD_Buffer,DVD_Status_TransportStatus,1)
	    
	    IF(DVD_Status_TransportStatus = "$00") { DVD_Status_TransportStatus = 'DVD_Off' }
	    ELSE IF(DVD_Status_TransportStatus = "$10") { DVD_Status_TransportStatus = 'Stop' }
	    ELSE IF(DVD_Status_TransportStatus = "$11") { DVD_Status_TransportStatus = 'Play' }
	    ELSE IF(DVD_Status_TransportStatus = "$12") { DVD_Status_TransportStatus = 'Pause' }
	    ELSE IF(DVD_Status_TransportStatus = "$20") { DVD_Status_TransportStatus = 'Load' }
	    ELSE IF(DVD_Status_TransportStatus = "$30") { DVD_Status_TransportStatus = 'FrDoor' }
	    ELSE IF(DVD_Status_TransportStatus = "$ee") { DVD_Status_TransportStatus = 'Error' }
	    ELSE IF(DVD_Status_TransportStatus = "$ff") { DVD_Status_TransportStatus = 'Unknown' }
	    vdvDVD_Buffer = ''
This works great, and I wind up with this:
cDiscNo1 = $01
cDiscNo2 = $39
cTitleNo1 = $00
cTitleNo2 = $04
cChapterNo1 = $00
cChapterNo2 = $04
DVD_Status_TranportStatus = 'Play'

Then I try to parse those into Integer values
nHexMunch = HEXTOI(cDiscNo1)
nDiscNo1 = (((nHexMunch/16 * 10) + (nHexMunch % 16))* 100)
nHexMunch = HEXTOI(cDiscNo2)
nDiscNo2 = ((nHexMunch/16 * 10) + (nHexMunch % 16))
nDiscNo = nDiscNo1 + nDiscNo2
And so on for the rest of them.

The result is:
nDiscNo1 = 0
nDiscNo2 = 9
nDiscNo = 9

Obviously, I'm expecting nDiscNo1 = 100, nDiscNo2 = 39, nDiscNo = 139
So it seems that the MOD 16 is working, but the rest isn't, and I can't for the life of me figure out why.

Anything obvious I'm missing?

Thanks guys!

Comments

  • DmAVSDmAVS Posts: 6
    I have also tried the function:
    define_function long bcdword(long bcd) {
      integer nib
      long dec
      dec = 0
      for (nib = 1; nib <= 8; nib++) {
        dec = dec*10 + ((bcd>>(32-nib*4))&$0F)
      }
      return dec
    }
    define_program
    WAIT 10			//Parse the hex status codes
    {
        nDiscNo1 = TYPE_CAST(bcdword(HEXTOI(cDiscNo1)))
        nDiscNo2 = TYPE_CAST(bcdword(HEXTOI(cDiscNo2)))
        nDiscNo = ((nDiscNo1 * 100) + nDiscNo2)
        nTitleNo1 = TYPE_CAST(bcdword(HEXTOI(cTitleNo1)))
        nTitleNo2 = TYPE_CAST(bcdword(HEXTOI(cTitleNo2)))
        nTitleNo = ((nTitleNo1 * 100) + nTitleNo2)
        nChapterNo1 = TYPE_CAST(bcdword(HEXTOI(cChapterNo1)))
        nChapterNo2 = TYPE_CAST(bcdword(HEXTOI(cChapterNo2)))
        nChapterNo = ((nChapterNo1 * 100) + nChapterNo2)
    }
    
    I know - It'll get moved out of mainline after I get it working, and put inline with the data_event, eliminating the hex step all together. This is just for testing.

    The result is the same with this code:
    nDiscNo1 = 0
    nDiscNo2 = 9
    nDiscNo = 9
  • DmAVS wrote: »
    Be warned, I'm knocking about 5 years of rust off of my ACE certification with an automated theater project. The DVD player is a Sony 400-Disc Blue-Ray changer (7000ES), and I'm connected VIA RS-232. The DVD player returns status strings prompted by polling from the module. The strings give the status of the movie playing, and I'm trying to use them to detect the position of a movie to automate theater start-up and shutdown. (A royal PITA)

    The issue I'm having is that the status is received as binary coded decimal. I've read a few threads here on how to parse and translate these strings into actual integers, but have so far been unsuccessful.

    The string consists of the header, 2 Disc number bytes, 2 title number bytes, 2 chapter number bytes, and a transport status byte. Anything after that I really don't care about, and erase the rest of the string.
    It looks like this, where:
    $88,$82 = Disc Data to follow
    $01,$39 = Disc Number (Disc 139)
    $00,$04 = Title number (Title #4)
    $00,$01 = Chapter number (Chapter 4)
    $11 = Transport status ($11 = Play)
    String From [41002:1:1]-[$02$0A$88$82$01$39$00$04$00$04$11$0C$C8]
    The DATA_EVENT looks like this:
    REMOVE_STRING(vdvDVD_Buffer,"$88,$82",1)
    	    cDiscNo1 = LEFT_STRING(vdvDVD_Buffer,1)
    	    REMOVE_STRING(vdvDVD_Buffer,cDiscNo1,1)
    	    cDiscNo2 = LEFT_STRING(vdvDVD_Buffer,1)
    	    REMOVE_STRING(vdvDVD_Buffer,cDiscNo2,1)
    	    cTitleNo1 = LEFT_STRING(vdvDVD_Buffer,1)
    	    REMOVE_STRING(vdvDVD_Buffer,cTitleNo1,1)
    	    cTitleNo2 = LEFT_STRING(vdvDVD_Buffer,1)
    	    REMOVE_STRING(vdvDVD_Buffer,cTitleNo2,1)
    	    cChapterNo1 = LEFT_STRING(vdvDVD_Buffer,1)
    	    REMOVE_STRING(vdvDVD_Buffer,cChapterNo1,1)
    	    cChapterNo2 = LEFT_STRING(vdvDVD_Buffer,1)
    	    REMOVE_STRING(vdvDVD_Buffer,cChapterNo2,1)
    	    DVD_Status_TransportStatus = LEFT_STRING(vdvDVD_Buffer,1)
    	    REMOVE_STRING(vdvDVD_Buffer,DVD_Status_TransportStatus,1)
    	    
    	    IF(DVD_Status_TransportStatus = "$00") { DVD_Status_TransportStatus = 'DVD_Off' }
    	    ELSE IF(DVD_Status_TransportStatus = "$10") { DVD_Status_TransportStatus = 'Stop' }
    	    ELSE IF(DVD_Status_TransportStatus = "$11") { DVD_Status_TransportStatus = 'Play' }
    	    ELSE IF(DVD_Status_TransportStatus = "$12") { DVD_Status_TransportStatus = 'Pause' }
    	    ELSE IF(DVD_Status_TransportStatus = "$20") { DVD_Status_TransportStatus = 'Load' }
    	    ELSE IF(DVD_Status_TransportStatus = "$30") { DVD_Status_TransportStatus = 'FrDoor' }
    	    ELSE IF(DVD_Status_TransportStatus = "$ee") { DVD_Status_TransportStatus = 'Error' }
    	    ELSE IF(DVD_Status_TransportStatus = "$ff") { DVD_Status_TransportStatus = 'Unknown' }
    	    vdvDVD_Buffer = ''
    
    This works great, and I wind up with this:
    cDiscNo1 = $01
    cDiscNo2 = $39
    cTitleNo1 = $00
    cTitleNo2 = $04
    cChapterNo1 = $00
    cChapterNo2 = $04
    DVD_Status_TranportStatus = 'Play'

    Then I try to parse those into Integer values
    nHexMunch = HEXTOI(cDiscNo1)
    nDiscNo1 = (((nHexMunch/16 * 10) + (nHexMunch % 16))* 100)
    nHexMunch = HEXTOI(cDiscNo2)
    nDiscNo2 = ((nHexMunch/16 * 10) + (nHexMunch % 16))
    nDiscNo = nDiscNo1 + nDiscNo2
    
    And so on for the rest of them.

    The result is:
    nDiscNo1 = 0
    nDiscNo2 = 9
    nDiscNo = 9

    Obviously, I'm expecting nDiscNo1 = 100, nDiscNo2 = 39, nDiscNo = 139
    So it seems that the MOD 16 is working, but the rest isn't, and I can't for the life of me figure out why.

    Anything obvious I'm missing?

    Thanks guys!

    The problem here is the HEXTOI function. This is looking for ASCII characters that make up a hex number, so something like "'35'", instead of "$35". With the first string, the HEXTOI function would return a value of 53. With the second, you would get a value of 5, since $35 is the equivalent of the ASCII 5. In your example, with a value of $01, HEXTOI is return 0, since that doesn't match up with the ASCII values for 0-9 or A-F. You get a 9 because $39 is an ASCII 9.

    To do what you want, you need to skip the HEXTOI function and just do the modulo and division operations on the cDiscNo1, etc. This should get you the result you want.
  • DmAVSDmAVS Posts: 6
    So I just need to get rid of the munching:
    nDiscNo1 = (((cDiscNo1/16 * 10) + (cDiscNo1 % 16))* 100)
    nDiscNo2 = ((nDiscNo2 /16 * 10) + (nDiscNo2 % 16))
    nDiscNo = nDiscNo1 + nDiscNo2
    

    That would certainly explain the same result with the math, and the function. I HEXTOI'd both of them...

    I'm going to need a beer if it was that easy...
  • BigsquatchBigsquatch Posts: 216
    Nevermind... Andrew is correct. I posted a solution but I misread the feedback and it wouldn't have worked.
  • Bigsquatch wrote: »
    You're getting closer with the 2nd example that you posted. Here's how I would do it (not tested.)
    REMOVE_STRING(vdvDVD_Buffer,"$88,$82",1)
    
    nDiscNo1 = ATOI(LEFT_STRING(vdvDVD_Buffer, 4))
    nTitleNo = ATOI(MID_STRING(vdvDVD_Buffer, 5, 4))
    nChapterNo = ATOI(MID_STRING(vdvDVD_Buffer, 9, 4))
    nTransport = ATOI(MID_STRING(vdvDVD_Buffer, 13, 2))
    

    This won't work either. Keep in mind that the characters that are getting returned do not necessarily map to a ASCII integer value. And if they do, it's not the integer value that DmAVS is looking for. You would only get an integer value if the hex value returned is between $30 and $39.
  • DmAVSDmAVS Posts: 6
    I've adjusted the DATA_EVENT:
    DATA_EVENT [vdvDVD]
    {
        ONLINE:
        {
    	SEND_COMMAND vdvDVD,'SET BAUD 9600,N,8,1'
    	SEND_COMMAND vdvDVD,"'PASSBACK-1'" 					//Set DVD Response passback to vdvDVD ON
        }
        STRING:
        {
    	vdvDVD_Buffer = "vdvDVD_Buffer,DATA.TEXT"
    	IF(FIND_STRING(vdvDVD_Buffer,"$88,$82",1))
    	{
    	    REMOVE_STRING(vdvDVD_Buffer,"$88,$82",1)
    	    cMunch = LEFT_STRING(vdvDVD_Buffer,1)
    	    REMOVE_STRING(vdvDVD_Buffer,cMunch,1)
    	    nDiscNo1 = (((cMunch/16 * 10) + (cMunch % 16))* 100)
    	    cMunch = LEFT_STRING(vdvDVD_Buffer,1)
    	    REMOVE_STRING(vdvDVD_Buffer,cMunch,1)
    	    nDiscNo2 = ((cMunch/16 * 10) + (cMunch % 16))
    	    nDiscNo = (nDiscNo1 + nDiscNo2)
    	    IF(nLastDiscNo != nDiscNo)
    	    {
    		PULSE[nDiscChanged]
    		nLastDiscNo = nDiscNo
    	    }
    	    cMunch = LEFT_STRING(vdvDVD_Buffer,1)
    	    REMOVE_STRING(vdvDVD_Buffer,cMunch,1)
    	    nTitleNo1 = (((cMunch/16 * 10) + (cMunch % 16))* 100)
    	    cMunch = LEFT_STRING(vdvDVD_Buffer,1)
    	    REMOVE_STRING(vdvDVD_Buffer,cMunch,1)
    	    nTitleNo2 = ((cMunch/16 * 10) + (cMunch % 16))
    	    nTitleNo = (nTitleNo1 + nTitleNo2)
    	    IF(nLastTitleNo != nTitleNo)
    	    {
    		PULSE[nTitleChanged]
    		nLastTitleNo = nTitleNo
    	    }
    	    cMunch = LEFT_STRING(vdvDVD_Buffer,1)
    	    REMOVE_STRING(vdvDVD_Buffer,cMunch,1)
    	    nChapterNo1 = (((cMunch/16 * 10) + (cMunch % 16))* 100)
    	    cMunch = LEFT_STRING(vdvDVD_Buffer,1)
    	    REMOVE_STRING(vdvDVD_Buffer,cMunch,1)
    	    nChapterNo2 = ((cMunch/16 * 10) + (cMunch % 16))
    	    nChapterNo = (nChapterNo1 + nChapterNo2)
    	    IF(nLastChapterNo > nChapterNo)
    	    {
    		PULSE[nChapterDecreased]
    		nLastChapterNo = nChapterNo
    	    }
    	    ELSE IF(nLastChapterNo < nChapterNo)
    	    {
    		PULSE[nChapterIncreased]
    		nLastChapterNo = nChapterNo
    	    }
    	    
    	    DVD_Status_TransportStatus = LEFT_STRING(vdvDVD_Buffer,1)
    	    REMOVE_STRING(vdvDVD_Buffer,DVD_Status_TransportStatus,1)
    	    IF(DVD_Status_TransportStatus = "$00") { DVD_Status_TransportStatus = 'DVD_Off' }
    	    ELSE IF(DVD_Status_TransportStatus = "$10") { DVD_Status_TransportStatus = 'Stop' }
    	    ELSE IF(DVD_Status_TransportStatus = "$11") { DVD_Status_TransportStatus = 'Play' }
    	    ELSE IF(DVD_Status_TransportStatus = "$12") { DVD_Status_TransportStatus = 'Pause' }
    	    ELSE IF(DVD_Status_TransportStatus = "$20") { DVD_Status_TransportStatus = 'Load' }
    	    ELSE IF(DVD_Status_TransportStatus = "$30") { DVD_Status_TransportStatus = 'FrDoor' }
    	    ELSE IF(DVD_Status_TransportStatus = "$ee") { DVD_Status_TransportStatus = 'Error' }
    	    ELSE IF(DVD_Status_TransportStatus = "$ff") { DVD_Status_TransportStatus = 'Unknown' }
    	    vdvDVD_Buffer = ''
    	}
    	ELSE IF(FIND_STRING(cBfvdvDVD,"$88,$8d",1))
    	{
    	    REMOVE_STRING(vdvDVD_Buffer,"$88,$8d",1)
    	    cMunch = LEFT_STRING(vdvDVD_Buffer,1)
    	    REMOVE_STRING(vdvDVD_Buffer,cMunch,1)
    	    cMunch = LEFT_STRING(vdvDVD_Buffer,1)
    	    REMOVE_STRING(vdvDVD_Buffer,cMunch,1)
    	    
    	    DVD_Status_DiscType = LEFT_STRING(vdvDVD_Buffer,1)
    	    REMOVE_STRING(vdvDVD_Buffer,DVD_Status_DiscType,1)
    	    
    	    IF(DVD_Status_DiscType = "$00") { DVD_Status_DiscType = 'NoDisc' }
    	    ELSE IF(DVD_Status_DiscType = "$01") { DVD_Status_DiscType = 'CDDA' }
    	    ELSE IF(DVD_Status_DiscType = "$03") { DVD_Status_DiscType = 'DVD-ROM' }
    	    ELSE IF(DVD_Status_DiscType = "$05") { DVD_Status_DiscType = 'BD-ROM' }
    	    ELSE IF(DVD_Status_DiscType = "$ff") { DVD_Status_DiscType = 'Unknown' }
    	    
    	    REMOVE_STRING(vdvDVD_Buffer,"$02",1)
    	    DVD_Status_Movie_Title = HEXTOI(vdvDVD_Buffer)
    	    IF(DVD_Status_Movie_Title)
    	    {
    		DVD_Title = DVD_Status_Movie_Title
    	    }
    	    vdvDVD_Buffer = ''
    	}
    	ELSE
    	{
    	    vdvDVD_Buffer = ''
    	}
        }
    }
    

    I'm getting the error:
    WARNING: C:\program.axs(1529): C10573: String used as a CHAR value in a math operation

    Am I correct in assuming that I should re-write this with type_cast() to resolve the issue because the string is a single hex value?
    Like:
    nDiscNo1 = (((type_cast(cMunch)/16 * 10) + (type_cast(cMunch) % 16))* 100)
    

    Note: This is why I was using HEXTOI in the first place - I was trying to pass the integer values of the hex strings to the math operation. Some rust is a little deeper than the rest ;)
  • That's correct. You don't really have to do anything, as the code will still work with that warning, but if you're like me, you don't like having warnings when you compile.
  • DmAVSDmAVS Posts: 6
    OK.
    It's all compiling now.

    I'll see how it works tonight.

    Thanks for the help!
  • DmAVSDmAVS Posts: 6
    Worked like a champ!

    Thanks guys!
Sign In or Register to comment.