Home AMX User Forum AMX Technical Discussion

Denon DNP720AE UTF-8 parsing

I am working with a DNP720. Unit mostly responds in ASCII for power/input etc. Parsing that works fine. When trying to get feedback from the display, the unit responds with:
"NSE8**************_?????<CR>
*:UTF-8 CODE Character(MAX95byte)
_:Null
?: Don't Care (The character after
Null should be disregarded)
※:Cursor&Playable Music
Information Data(1Byte)
Bit1:Playable Music =1
Bit2,3:Don't Care
Bit4:CURSOR SELECT=1
Bit5,6,7,8:Don't Care
************_?????:96byte Fixed

I have to admit my lack of experience with Unicode. I did follow the technote and enabled unicode in NS. I included the UnicodeLib.axi with my file. TP font is Lucida Unicode.
Meat of the code below. Forgive me, I ran out of time with it yesterday, commented it out and am coming back to it today. In the code below, I was just trying to get the string relayed to the TP with no parsing and get it to display correctly. All I get is gabbledy-gook. I have tried Times New Roman, as well as Arial 12 and Arial bold. Office shows that I have Arial Unicode MS on my machine, but it doesn't show as an option in TPD4...

In the end, I want to remove the NSE from the string, use the number to get a value for the structure, compare the incoming data to the stored data up to the '_', update stored data if needed, and send to TP if updated.
Baby steps, how do I get get the UTF-8 string sent to the TP in it's entirety and have it display correctly?
DEFINE_TYPE
STRUCTURE stDEN_DNP720_STRUCTURE
{
WIDECHAR cDISP_DATA[135]
}
DEFINE_VARIABLE
VOLATILE stDEN_DNP720_STRUCTURE stDISPLINE 
VOLATILE stDEN_DNP720_STRUCTURE stDISPLINEARRAY [9]

VOLATILE CHAR cDEN_DNP720_BUFFER [1500]
VOLATILE CHAR cDEN_DNP720_DATA [135]
VOLATILE WIDECHAR wcDEN_DNP720_DATA [135]
VOLATILE INTEGER nLINE	=	0
VOLATILE CHAR cTRASH	

DEFINE_START
INCLUDE 'UnicodeLib.axi'

DEFINE_EVENT
DATA_EVENT[dvDEN720]
{
STRING:
	{
	LOCAL_VAR CHAR cTPSTRING [500]
	cDEN_DNP720_BUFFER = "cDEN_DNP720_BUFFER,DATA.TEXT"
	wcDEN_DNP720_DATA = _wc(data.text)
	WHILE (FIND_STRING(cDEN_DNP720_BUFFER,"$0D",1))
		{
		cDEN_DNP720_DATA = REMOVE_STRING (cDEN_DNP720_BUFFER,"$0D",1)
		SELECT
			{
			ACTIVE (FIND_STRING(cDEN_DNP720_DATA,"'PWON'",1)):
				{
				nDEN_DNP720_POWER = conPWR_ON
				}
			ACTIVE (FIND_STRING(cDEN_DNP720_DATA,"'PWSTANDBY'",1)):
				{
				nDEN_DNP720_POWER = conPWR_OFF
				}
			ACTIVE (FIND_STRING(cDEN_DNP720_DATA,"'NSE'",1)):
				{
				REMOVE_STRING (cDEN_DNP720_DATA,"'NSE'",1)
				nLINE = ATOI(LEFT_STRING(cDEN_DNP720_DATA,1))+1
				cTRASH = GET_BUFFER_CHAR(cDEN_DNP720_DATA)
				//cDEN_DNP720_DATA = LEFT_STRING (cDEN_DNP720_DATA,(FIND_STRING(cDEN_DNP720_DATA,"'_'",1)-1))
				cTPSTRING = WC_TP_ENCODE(wcDEN_DNP720_DATA)
				SEND_COMMAND dvTPKITSERVER,  "'^UNI-',ITOA(nLINE+210),',0,',cTPSTRING "

Comments

  • viningvining Posts: 4,368
    I have nothing to test this code with but this may work.
    ACTIVE(FIND_STRING(cDEN_DNP720_DATA,"'NSE'",1)):
    	  {
    	  STACK_VAR INTEGER nFBS ;
    	  
    	  nFBS = FIND_STRING(cDEN_DNP720_DATA,"'NSE'",1) ;
    	  if(nFBS > 1)//remove anything ahead of NSE
    	       {
    	       cTRASH = GET_BUFFER_STRING(cDEN_DNP720_DATA,nFBS-1) ;
    	       }
    	  nLINE = (ATOI(GET_BUFFER_STRING(cDEN_DNP720_DATA,4))+1) ;//remove 1st 4 character  NSE + # (0-8)
    	  nFBS = FIND_STRING(cDEN_DNP720_DATA,"'_'",1) ;// is '_' the actual char or is it a real null?
    	  if(nFBS)
    	       {
    	       STACK_VAR WIDECHAR cSTRING1[500] ;
    	       STACK_VAR CHAR cSTRING2[500] ;
    	       
    	       cSTRING1 = WC_DECODE(GET_BUFFER_STRING(cDEN_DNP720_DATA,nFBS-1),WC_FORMAT_UTF8,1) ; 
    	       cSTRING2 = WC_ENCODE(cSTRING1,WC_FORMAT_TP,1) ;
    	       
    	       SEND_STRING 0,"'DENON DEBUG: RX DATA UTF 8  DECODE-[ ',cSTRING1,' ] <',ITOA(__LINE__),'>'" ;
    	       SEND_STRING 0,"'DENON DEBUG: RX DATA UTF TP ENCODE-[ ',cSTRING2,' ] <',ITOA(__LINE__),'>'" ;
    	
    	       SEND_COMMAND dvTPKITSERVER,  "'^UNI-',ITOA(nLINE+210),',0,',cSTRING2" ;
    	       }
    	  else
    	       {
    	       SEND_STRING 0,"'DENON DEBUG: ERROR IN RX DATA FORMAT-[ ',cDEN_DNP720_DATA,' ] <',ITOA(__LINE__),'>'" ;
    	       }
    	  }
    
  • Thank you very much Vining. That did work as expected...sort of.. I had to change the '_' to $0D for the end of the string.

    The sort of part is the 'CURSOR'. The NSE and line number parsing work great. Once it gets to the cursor byte, it goes south. Past the cursor, we are back to plain ASCII and that part works as well. The problem is that the cursor byte changes values based on what menu you are in. In most menus, the non-highlighted line has a $01 value. In some menus, this changes to $02. In some menus, for the line that has the cursor, the value is $08, $09, or $0A. Possibly more options, but this is what I have seen so far.
    I think I am going to create a multi-state button that sits on the TP just before each line of text and change its state based on this byte. I will put a bitmap in each state that reflects menu option. I was hoping that by just relaying the unicode back to the TP that the correct character would come up at the beginning of each line, but not the case.

    Thanks again for the help. I will let you know how it turns out.

    Jason
  • viningvining Posts: 4,368
    In the instructions they call '_' a null so maybe it is a real null $00 and they just used '_' to represent it.

    If so you can change:
    nFBS = FIND_STRING(cDEN_DNP720_DATA,"'_'",1) ;// is '_' the actual char or is it a real null?
    
    to
    
    nFBS = FIND_STRING(cDEN_DNP720_DATA,"$00",1) ;
    
    To me it looks like when you get an NSE1-NSE6 you'll need to remove the 1st byte after the NSE# is removed, prior to doing the find_string on '_' or null as the case may be and then do a bitwise comparison on the Cursor byte to check the status of bit 1 & 4.

    Edit added...

    I never do bitwise comparison so I figured I'd give it a try. It compiled without error so it might work.
             ACTIVE(FIND_STRING(cDEN_DNP720_DATA,"'NSE'",1)):
    	       {
    	       STACK_VAR INTEGER nFBS ;
    	       
    	       nFBS = FIND_STRING(cDEN_DNP720_DATA,"'NSE'",1) ;
    	       if(nFBS > 1)//remove anything ahead of NSE
    		    {
    		    cTRASH = GET_BUFFER_STRING(cDEN_DNP720_DATA,nFBS-1) ;
    		    }
    	       nLINE = (ATOI(GET_BUFFER_STRING(cDEN_DNP720_DATA,4))+1) ;//remove 1st 4 character  NSE + # (0-8)
    	       if(nLINE && nLINE < 7)//1-6
    		    {
    		    STACK_VAR CHAR cCursorByte ;
    		    STACK_VAR INTEGER nPlayable ;
    		    STACK_VAR INTEGER nCursorSelect ;
    		    
    		    cCursorByte = GET_BUFFER_CHAR(cDEN_DNP720_DATA) ;
    		    nPlayable = (cCursorByte & $1) ;
    		    nCursorSelect = ((cCursorByte & $8) == $8) ;
    		    
    		    SEND_STRING 0,"'DENON DEBUG: RX DATA Playable Music-[ ',itoa(nPlayable),' ] <',ITOA(__LINE__),'>'" ;
    		    SEND_STRING 0,"'DENON DEBUG: RX DATA  Cursor Select-[ ',itoa(nCursorSelect),' ] <',ITOA(__LINE__),'>'" ;
    		    }
    	       nFBS = FIND_STRING(cDEN_DNP720_DATA,$00,1) ;// is '_' the actual char or is it a real null?
    	       if(nFBS)
    		    {
    		    STACK_VAR WIDECHAR cSTRING1[500] ;
    		    STACK_VAR CHAR cSTRING2[500] ;
    		    
    		    cSTRING1 = WC_DECODE(GET_BUFFER_STRING(cDEN_DNP720_DATA,nFBS-1),WC_FORMAT_UTF8,1) ; 
    		    cSTRING2 = WC_ENCODE(cSTRING1,WC_FORMAT_TP,1) ;
    		    
    		    SEND_STRING 0,"'DENON DEBUG: RX DATA UTF 8  DECODE-[ ',cSTRING1,' ] <',ITOA(__LINE__),'>'" ;
    		    SEND_STRING 0,"'DENON DEBUG: RX DATA UTF TP ENCODE-[ ',cSTRING2,' ] <',ITOA(__LINE__),'>'" ;
    	     
    		    SEND_COMMAND dvTPKITSERVER,  "'^UNI-',ITOA(nLINE+210),',0,',cSTRING2" ;
    		    }
    	       else
    		    {
    		    SEND_STRING 0,"'DENON DEBUG: ERROR IN RX DATA FORMAT-[ ',cDEN_DNP720_DATA,' ] <',ITOA(__LINE__),'>'" ;
    		    }
    	       }
    
  • vining wrote: »
    In the instructions they call '_' a null so maybe it is a real null $00 and they just used '_' to represent it.

    If so you can change:
    nFBS = FIND_STRING(cDEN_DNP720_DATA,"'_'",1) ;// is '_' the actual char or is it a real null?
    
    to
    
    nFBS = FIND_STRING(cDEN_DNP720_DATA,"$00",1) ;
    
    originally, I was using:

    cDEN_DNP720_DATA = LEFT_STRING (cDEN_DNP720_DATA,(FIND_STRING(cDEN_DNP720_DATA,"'_'",1)-1))
    to remove the string and it worked just fine. After using the Unicode code that you posted, I had to change it to:

    nFBS = FIND_STRING(cDEN_DNP720_DATA,"$0D",1) ;// is '_' the actual char or is it a real null?
    to get it to parse. It works this way. No wasted characters at the end of the string.
    To me it looks like when you get an NSE1-NSE6 you'll need to remove the 1st byte after the NSE# is removed, prior to doing the find_string on '_' or null as the case may be and then do a bitwise comparison on the Cursor byte to check the status of bit 1 & 4.

    Edit added...

    I never do bitwise comparison so I figured I'd give it a try. It compiled without error so it might work.
             ACTIVE(FIND_STRING(cDEN_DNP720_DATA,"'NSE'",1)):
    	       {
    	       STACK_VAR INTEGER nFBS ;
    	       
    	       nFBS = FIND_STRING(cDEN_DNP720_DATA,"'NSE'",1) ;
    	       if(nFBS > 1)//remove anything ahead of NSE
    		    {
    		    cTRASH = GET_BUFFER_STRING(cDEN_DNP720_DATA,nFBS-1) ;
    		    }
    	       nLINE = (ATOI(GET_BUFFER_STRING(cDEN_DNP720_DATA,4))+1) ;//remove 1st 4 character  NSE + # (0-8)
    	       if(nLINE && nLINE < 7)//1-6
    		    {
    		    STACK_VAR CHAR cCursorByte ;
    		    STACK_VAR INTEGER nPlayable ;
    		    STACK_VAR INTEGER nCursorSelect ;
    		    
    		    cCursorByte = GET_BUFFER_CHAR(cDEN_DNP720_DATA) ;
    		    nPlayable = (cCursorByte & $1) ;
    		    nCursorSelect = ((cCursorByte & $8) == $8) ;
    		    
    		    SEND_STRING 0,"'DENON DEBUG: RX DATA Playable Music-[ ',itoa(nPlayable),' ] <',ITOA(__LINE__),'>'" ;
    		    SEND_STRING 0,"'DENON DEBUG: RX DATA  Cursor Select-[ ',itoa(nCursorSelect),' ] <',ITOA(__LINE__),'>'" ;
    		    }
    	       nFBS = FIND_STRING(cDEN_DNP720_DATA,$00,1) ;// is '_' the actual char or is it a real null?
    	       if(nFBS)
    		    {
    		    STACK_VAR WIDECHAR cSTRING1[500] ;
    		    STACK_VAR CHAR cSTRING2[500] ;
    		    
    		    cSTRING1 = WC_DECODE(GET_BUFFER_STRING(cDEN_DNP720_DATA,nFBS-1),WC_FORMAT_UTF8,1) ; 
    		    cSTRING2 = WC_ENCODE(cSTRING1,WC_FORMAT_TP,1) ;
    		    
    		    SEND_STRING 0,"'DENON DEBUG: RX DATA UTF 8  DECODE-[ ',cSTRING1,' ] <',ITOA(__LINE__),'>'" ;
    		    SEND_STRING 0,"'DENON DEBUG: RX DATA UTF TP ENCODE-[ ',cSTRING2,' ] <',ITOA(__LINE__),'>'" ;
    	     
    		    SEND_COMMAND dvTPKITSERVER,  "'^UNI-',ITOA(nLINE+210),',0,',cSTRING2" ;
    		    }
    	       else
    		    {
    		    SEND_STRING 0,"'DENON DEBUG: ERROR IN RX DATA FORMAT-[ ',cDEN_DNP720_DATA,' ] <',ITOA(__LINE__),'>'" ;
    		    }
    	       }
    

    I was thinking this also, and will think about this on my long drive today(7 hours round trip for a service call). If it is just bits 1 and 4, I have seen $01, $02, $08, $09, and $0A as values in this bit. I seem to remember more, and will have to check. With just 2 toggling bits, this seems like more than the possible values??
  • viningvining Posts: 4,368
    My thinking is the '_' is just an symbol for $00 since there's no ascii representation for a null other than the word null so me thinks that's why you had to change it to $0D cuz there wasn't really a '_' to find but there should be a $00 instead.


    Are you looking at the entire byte when you say "I have seen $01, $02, $08, $09, and $0A as values in this bit" cuz a bit as you called it can't be anything other than a 1 or 0 but if you're looking at the entire byte (8 bits) then you have quite a few possibilities. Assuming all bits other than 1 and 4 will always come in as 0 then you have 4 possibilities, $9, $8, $1 and $0 or
    00001001, 00001000, 00000001 and 0000000.

    Now that's assuming that the other bits we don't care about are always going to be 0. We can't assume that so we have to do a bitwise comparison for the bits we are concerned about. Bits 1 and 4. If it were confirmed that all the other bits will always be 0 then you could look for 9 (both flags set), 8 (cursor flag set), 1 (Playable flag set) or 0 (no flags set) but until that's confirmed you'll need to do the bitwise compare.
Sign In or Register to comment.